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

---
 src/client/views/collections/CollectionSchemaView.tsx | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 42843ad30..31de4e146 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -287,9 +287,10 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; }
     @computed get tableWidth() { return this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH - this.previewWidth(); }
     @computed get columns() {
+        console.log("columns");
         return Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField), []);
     }
-    set columns(columns: SchemaHeaderField[]) { this.props.Document.schemaColumns = new List<SchemaHeaderField>(columns); }
+    set columns(columns: SchemaHeaderField[]) { console.log("setting columns"); this.props.Document.schemaColumns = new List<SchemaHeaderField>(columns); }
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
         let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.heading.toUpperCase() === key.toUpperCase()) === -1);
@@ -404,7 +405,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         super(props);
         // convert old schema columns (list of strings) into new schema columns (list of schema header fields)
         let oldSchemaColumns = Cast(this.props.Document.schemaColumns, listSpec("string"), []);
-        if (oldSchemaColumns && oldSchemaColumns.length) {
+        if (oldSchemaColumns && oldSchemaColumns.length && typeof oldSchemaColumns[0] !== "object") {
+            console.log("REMAKING COLUMNs");
             let newSchemaColumns = oldSchemaColumns.map(i => typeof i === "string" ? new SchemaHeaderField(i) : i);
             this.props.Document.schemaColumns = new List<SchemaHeaderField>(newSchemaColumns);
         }
@@ -583,6 +585,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let index = 0;
         let found = this.columns.findIndex(col => col.heading.toUpperCase() === "New field".toUpperCase()) > -1;
         if (!found) {
+            console.log("create column found");
             this.columns.push(new SchemaHeaderField("New field"));
             return;
         }
@@ -590,13 +593,16 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             index++;
             found = this.columns.findIndex(col => col.heading.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1;
         }
+        console.log("create column new");
         this.columns.push(new SchemaHeaderField("New field (" + index + ")"));
     }
 
     @action
     deleteColumn = (key: string) => {
+        console.log("deleting columnnn");
         let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField));
         if (list === undefined) {
+            console.log("delete column");
             this.props.Document.schemaColumns = list = new List<SchemaHeaderField>([]);
         } else {
             const index = list.map(c => c.heading).indexOf(key);
@@ -608,10 +614,13 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @action
     changeColumns = (oldKey: string, newKey: string, addNew: boolean) => {
+        console.log("changingin columnsdfhs");
         let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField));
         if (list === undefined) {
+            console.log("change columns new");
             this.props.Document.schemaColumns = list = new List<SchemaHeaderField>([new SchemaHeaderField(newKey)]);
         } else {
+            console.log("change column");
             if (addNew) {
                 this.columns.push(new SchemaHeaderField(newKey));
             } else {
-- 
cgit v1.2.3-70-g09d2


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

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

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

diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 3c3708a30..c1f53f159 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -8,7 +8,8 @@
     box-sizing: border-box;
     // position: absolute;
     width: 100%;
-    height: calc(100% - 70px);
+    transition: height .5s;
+    height: 100%;
     // overflow: hidden;
     // overflow-x: scroll;
     // border: none;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 7bd0b5965..7463429e0 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -237,8 +237,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         // if (SelectionManager.SelectedDocuments().length > 0) console.log(StrCast(SelectionManager.SelectedDocuments()[0].Document.title));
         // if (DocumentManager.Instance.getDocumentView(this.props.Document)) console.log(StrCast(this.props.Document.title), SelectionManager.IsSelected(DocumentManager.Instance.getDocumentView(this.props.Document)!))
         return (
-            <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
-                onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createTarget}>
+            <div className="collectionSchemaView-container" style={{ height: this.chromeCollapsed ? "100%" : "calc(100% - 70px" }}
+                onPointerDown={this.onPointerDown} onWheel={this.onWheel} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createTarget}>
                 {this.schemaTable}
                 {this.dividerDragger}
                 {!this.previewWidth() ? (null) : this.previewPanel}
diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss
index 6525f3b07..f9f3ce473 100644
--- a/src/client/views/collections/CollectionViewChromes.scss
+++ b/src/client/views/collections/CollectionViewChromes.scss
@@ -4,7 +4,7 @@
 .collectionViewChrome-cont {
     position: relative;
     z-index: 9001;
-    transition: top .5s;
+    transition: margin-top .5s;
     background: lightslategray;
     padding: 10px;
 
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 9c751c4df..2bffe3cc0 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -185,11 +185,11 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
 
     render() {
         return (
-            <div className="collectionViewChrome-cont" style={{ top: this._collapsed ? -100 : 0 }}>
+            <div className="collectionViewChrome-cont" style={{ marginTop: this._collapsed ? -70 : 0, height: 70 }}>
                 <div className="collectionViewChrome">
                     <div className="collectionViewBaseChrome">
                         <button className="collectionViewBaseChrome-collapse"
-                            style={{ top: this._collapsed ? 90 : 10, transform: `rotate(${this._collapsed ? 180 : 0}deg)` }}
+                            style={{ marginTop: this._collapsed ? 60 : 0, transform: `rotate(${this._collapsed ? 180 : 0}deg)` }}
                             title="Collapse collection chrome" onClick={this.toggleCollapse}>
                             <FontAwesomeIcon icon="caret-up" size="2x" />
                         </button>
-- 
cgit v1.2.3-70-g09d2


From 5aa5bded4e90ec29bccac221ec115f5cd2f30791 Mon Sep 17 00:00:00 2001
From: Fawn <fangrui_tong@brown.edu>
Date: Mon, 29 Jul 2019 11:58:25 -0400
Subject: reverted schematable childdocs back since tables won't rerender on
 change otherwise

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

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

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


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

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

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

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


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

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

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

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


From f1cb6a2212b11ba6d18dfa2e800b2c8e4ad94a88 Mon Sep 17 00:00:00 2001
From: fawn <fangrui_tong@brown.edu>
Date: Mon, 29 Jul 2019 14:28:25 -0400
Subject: made hit box on col resizer smaller and hit box on coll expander
 bigger

---
 src/client/documents/Documents.ts                  |  8 ++---
 src/client/views/MainView.tsx                      |  2 +-
 .../views/collections/CollectionSchemaCells.tsx    |  2 +-
 .../views/collections/CollectionSchemaView.scss    | 39 +++++++++++++++-------
 .../views/collections/CollectionSchemaView.tsx     |  6 ++--
 .../collections/collectionFreeForm/MarqueeView.tsx |  2 +-
 src/client/views/nodes/LinkEditor.tsx              |  2 +-
 src/client/views/nodes/LinkMenuGroup.tsx           |  2 +-
 src/new_fields/SchemaHeaderField.ts                |  4 +--
 9 files changed, 41 insertions(+), 26 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index ee1b9fd0d..01e3ced5d 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -404,7 +404,7 @@ export namespace Docs {
         }
 
         export function FreeformDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Freeform });
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Freeform });
         }
 
         export function SchemaDocument(schemaColumns: SchemaHeaderField[], documents: Array<Doc>, options: DocumentOptions) {
@@ -412,15 +412,15 @@ export namespace Docs {
         }
 
         export function TreeDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Tree });
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Tree });
         }
 
         export function StackingDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Stacking });
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Stacking });
         }
 
         export function MasonryDocument(documents: Array<Doc>, options: DocumentOptions) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title")]), ...options, viewType: CollectionViewType.Masonry });
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Masonry });
         }
 
         export function ButtonDocument(options?: DocumentOptions) {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index f5a6715e5..d4c0711a2 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -375,7 +375,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([new SchemaHeaderField("title")], [], { width: 200, height: 200, title: "a schema collection" }));
+        let addSchemaNode = action(() => Docs.Create.SchemaDocument([new SchemaHeaderField("title", "#f1efeb")], [], { 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 194765880..e06a5c66b 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -108,7 +108,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
                 this._document[fieldKey] = de.data.draggedDocuments[0];
             }
             else {
-                let coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title")], de.data.draggedDocuments, {});
+                let coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title", "f1efeb")], de.data.draggedDocuments, {});
                 this._document[fieldKey] = coll;
             }
             e.stopPropagation();
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 053d6452c..749b9a364 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -97,15 +97,6 @@
             // margin-right: -30px;
         }
 
-        .rt-resizable-header {
-            padding: 0;
-            height: 30px;
-
-            &:last-child {
-                overflow: visible;
-            }
-        }
-
         .rt-resizable-header-content {
             height: 100%;
             overflow: visible;
@@ -198,8 +189,22 @@
     }
 
     .rt-resizer {
-        width: 20px;
-        right: -10px;
+        width: 8px;
+        right: -4px;
+    }
+
+    .rt-resizable-header {
+        padding: 0;
+        height: 30px;
+    }
+
+    .rt-resizable-header:last-child {
+        overflow: visible;
+        border: 3px solid red !important;
+
+        .rt-resizer {
+            width: 5px !important;
+        }
     }
 }
 
@@ -318,7 +323,7 @@ button.add-column {
         input[type="radio"] {
             display: none;
         }
-        
+
         .columnMenu-colorPicker {
             width: 20px;
             height: 20px;
@@ -497,4 +502,14 @@ button.add-column {
 
 .collectionSchemaView-expander {
     height: 100%;
+    min-height: 30px;
+    position: relative;
+    color: gray;
+
+    svg {
+        position: absolute;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 53dd9523b..ece638ec7 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -635,15 +635,15 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField));
         if (list === undefined) {
             console.log("change columns new");
-            this.props.Document.schemaColumns = list = new List<SchemaHeaderField>([new SchemaHeaderField(newKey, "f1efeb")]);
+            this.props.Document.schemaColumns = list = new List<SchemaHeaderField>([new SchemaHeaderField(newKey, "#f1efeb")]);
         } else {
             console.log("change column");
             if (addNew) {
-                this.columns.push(new SchemaHeaderField(newKey, "f1efeb"));
+                this.columns.push(new SchemaHeaderField(newKey, "#f1efeb"));
             } else {
                 const index = list.map(c => c.heading).indexOf(oldKey);
                 if (index > -1) {
-                    list[index] = new SchemaHeaderField(newKey, "f1efeb");
+                    list[index] = new SchemaHeaderField(newKey, "#f1efeb");
                 }
             }
         }
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 1c767e012..7decadbe9 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -135,7 +135,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 doc.width = 200;
                 docList.push(doc);
             }
-            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 });
+            let newCol = Docs.Create.SchemaDocument([...(groupAttr ? [new SchemaHeaderField("_group", "#f1efeb")] : []), ...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 0ea948c81..ecb3e9db4 100644
--- a/src/client/views/nodes/LinkEditor.tsx
+++ b/src/client/views/nodes/LinkEditor.tsx
@@ -290,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]].map(c => new SchemaHeaderField(c));
+        let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb"));
         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 0cb216aa6..e04044266 100644
--- a/src/client/views/nodes/LinkMenuGroup.tsx
+++ b/src/client/views/nodes/LinkMenuGroup.tsx
@@ -72,7 +72,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]].map(c => new SchemaHeaderField(c));
+        let cols = ["anchor1", "anchor2", ...[...keys]].map(c => new SchemaHeaderField(c, "#f1efeb"));
         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 d124a3907..475296d5c 100644
--- a/src/new_fields/SchemaHeaderField.ts
+++ b/src/new_fields/SchemaHeaderField.ts
@@ -48,12 +48,12 @@ export class SchemaHeaderField extends ObjectField {
     color: string;
     type: number;
 
-    constructor(heading: string = "", color?: string, type?: ColumnType) {
+    constructor(heading: string = "", color: string, type?: ColumnType) {
         console.log("CREATING SCHEMA HEADER FIELD");
         super();
 
         this.heading = heading;
-        this.color = color === "" || color === undefined ? RandomPastel() : color;
+        this.color = color === undefined ? "#000" : color;
         if (type) {
             this.type = type;
         }
-- 
cgit v1.2.3-70-g09d2


From 1190dc51c66cb48d48c16988f14100fd9a7004e2 Mon Sep 17 00:00:00 2001
From: fawn <fangrui_tong@brown.edu>
Date: Mon, 29 Jul 2019 17:34:57 -0400
Subject: color + type on schemaheaderfields fixed and schemas can toggle
 textwrapping

---
 .../views/collections/CollectionSchemaCells.tsx    |   4 +-
 .../views/collections/CollectionSchemaHeaders.tsx  |  82 +++++-----
 .../views/collections/CollectionSchemaView.scss    |  13 +-
 .../views/collections/CollectionSchemaView.tsx     | 175 ++++++++++-----------
 .../views/collections/CollectionViewChromes.tsx    |  33 ++++
 .../collections/collectionFreeForm/MarqueeView.tsx |   2 +-
 src/new_fields/SchemaHeaderField.ts                |  11 +-
 7 files changed, 183 insertions(+), 137 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index e06a5c66b..17dfd317d 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -108,7 +108,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
                 this._document[fieldKey] = de.data.draggedDocuments[0];
             }
             else {
-                let coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title", "f1efeb")], de.data.draggedDocuments, {});
+                let coll = Docs.Create.SchemaDocument([new SchemaHeaderField("title", "#f1efeb")], de.data.draggedDocuments, {});
                 this._document[fieldKey] = coll;
             }
             e.stopPropagation();
@@ -284,7 +284,7 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
         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);
+            this.applyToDoc(this._document, this.props.row, this.props.col, script.run);
         }
     }
 
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index 387107c55..088ad7ecd 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -23,23 +23,25 @@ export interface HeaderProps {
     onSelect: (oldKey: string, newKey: string, addnew: boolean) => void;
     setIsEditing: (isEditing: boolean) => void;
     deleteColumn: (column: string) => void;
-    setColumnType: (key: string, type: ColumnType) => void;
+    setColumnType: (column: SchemaHeaderField, type: ColumnType) => void;
     setColumnSort: (key: string, desc: boolean) => void;
     removeColumnSort: (key: string) => void;
+    setColumnColor: (column: SchemaHeaderField, color: string) => void;
+
 }
 
 export class CollectionSchemaHeader extends React.Component<HeaderProps> {
     render() {
         let icon: IconProp = this.props.keyType === ColumnType.Number ? "hashtag" : this.props.keyType === ColumnType.String ? "font" :
             this.props.keyType === ColumnType.Boolean ? "check-square" : this.props.keyType === ColumnType.Doc ? "file" : "align-justify";
-
         return (
             <div className="collectionSchemaView-header" style={{ background: this.props.keyValue.color }}>
                 <CollectionSchemaColumnMenu
-                    keyValue={this.props.keyValue.heading}
+                    columnField={this.props.keyValue}
+                    // keyValue={this.props.keyValue.heading}
                     possibleKeys={this.props.possibleKeys}
                     existingKeys={this.props.existingKeys}
-                    keyType={this.props.keyType}
+                    // keyType={this.props.keyType}
                     typeConst={this.props.typeConst}
                     menuButtonContent={<div><FontAwesomeIcon icon={icon} size="sm" />{this.props.keyValue.heading}</div>}
                     addNew={false}
@@ -50,6 +52,7 @@ export class CollectionSchemaHeader extends React.Component<HeaderProps> {
                     setColumnType={this.props.setColumnType}
                     setColumnSort={this.props.setColumnSort}
                     removeColumnSort={this.props.removeColumnSort}
+                    setColumnColor={this.props.setColumnColor}
                 />
             </div>
         );
@@ -73,10 +76,11 @@ export class CollectionSchemaAddColumnHeader extends React.Component<AddColumnHe
 
 
 export interface ColumnMenuProps {
-    keyValue: string;
+    columnField: SchemaHeaderField;
+    // keyValue: string;
     possibleKeys: string[];
     existingKeys: string[];
-    keyType: ColumnType;
+    // keyType: ColumnType;
     typeConst: boolean;
     menuButtonContent: JSX.Element;
     addNew: boolean;
@@ -84,10 +88,11 @@ export interface ColumnMenuProps {
     setIsEditing: (isEditing: boolean) => void;
     deleteColumn: (column: string) => void;
     onlyShowOptions: boolean;
-    setColumnType: (key: string, type: ColumnType) => void;
+    setColumnType: (column: SchemaHeaderField, type: ColumnType) => void;
     setColumnSort: (key: string, desc: boolean) => void;
     removeColumnSort: (key: string) => void;
     anchorPoint?: any;
+    setColumnColor: (column: SchemaHeaderField, color: string) => void;
 }
 @observer
 export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps> {
@@ -110,16 +115,21 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
         }
     }
 
+    setNewColor = (color: string): void => {
+        this.changeColumnType(ColumnType.Any);
+        console.log("change color", this.props.columnField.heading);
+        this.props.setColumnColor(this.props.columnField, color);
+    }
+
     @action
     toggleIsOpen = (): void => {
         this._isOpen = !this._isOpen;
         this.props.setIsEditing(this._isOpen);
     }
 
-    setColumnType = (oldKey: string, newKey: string, addnew: boolean) => {
-        let typeStr = newKey as keyof typeof ColumnType;
-        let type = ColumnType[typeStr];
-        this.props.setColumnType(this.props.keyValue, type);
+    changeColumnType = (type: ColumnType): void => {
+        console.log("change type", this.props.columnField.heading);
+        // this.props.setColumnType(this.props.columnField, type);
     }
 
     @action
@@ -129,33 +139,29 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
         }
     }
 
-    changeColumnColor = (color: string): void => {
-
-    }
-
     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)}>
+                    <button title="Any" className={this.props.columnField.type === ColumnType.Any ? "active" : ""} onClick={() => this.changeColumnType(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)}>
+                    <button title="Number" className={this.props.columnField.type === ColumnType.Number ? "active" : ""} onClick={() => this.changeColumnType(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)}>
+                    <button title="String" className={this.props.columnField.type === ColumnType.String ? "active" : ""} onClick={() => this.changeColumnType(ColumnType.String)}>
                         <FontAwesomeIcon icon={"font"} size="sm" />
                     </button>
-                    <button title="Checkbox" className={this.props.keyType === ColumnType.Boolean ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Boolean)}>
+                    <button title="Checkbox" className={this.props.columnField.type === ColumnType.Boolean ? "active" : ""} onClick={() => this.changeColumnType(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)}>
+                    <button title="Document" className={this.props.columnField.type === ColumnType.Doc ? "active" : ""} onClick={() => this.changeColumnType(ColumnType.Doc)}>
                         <FontAwesomeIcon icon={"file"} size="sm" />
                     </button>
                 </div>
-            </div>
+            </div >
         );
     }
 
@@ -164,9 +170,9 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
             <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 className="columnMenu-option" onClick={() => this.props.setColumnSort(this.props.columnField.heading, false)}>Sort ascending</div>
+                    <div className="columnMenu-option" onClick={() => this.props.setColumnSort(this.props.columnField.heading, true)}>Sort descending</div>
+                    <div className="columnMenu-option" onClick={() => this.props.removeColumnSort(this.props.columnField.heading)}>Clear sorting</div>
                 </div>
             </div>
         );
@@ -177,29 +183,29 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
             <div className="collectionSchema-headerMenu-group">
                 <label>Color:</label>
                 <div className="columnMenu-colors">
-                    <input type="radio" name="column-color" id="pink" value="#FFB4E8" onClick={() => this.changeColumnColor("#FFB4E8")} />
+                    <input type="radio" name="column-color" id="pink" value="#FFB4E8" onClick={() => this.setNewColor("#FFB4E8")} />
                     <label htmlFor="pink">
                         <div className="columnMenu-colorPicker" style={{ backgroundColor: "#FFB4E8" }}></div>
                     </label>
-                    <input type="radio" name="column-color" id="purple" value="#b28dff" onClick={() => this.changeColumnColor("#b28dff")} />
+                    <input type="radio" name="column-color" id="purple" value="#b28dff" onClick={() => this.setNewColor("#b28dff")} />
                     <label htmlFor="purple">
-                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#FFB4E8" }}></div>
+                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#b28dff" }}></div>
                     </label>
-                    <input type="radio" name="column-color" id="blue" value="#afcbff" onClick={() => this.changeColumnColor("#afcbff")} />
+                    <input type="radio" name="column-color" id="blue" value="#afcbff" onClick={() => this.setNewColor("#afcbff")} />
                     <label htmlFor="blue">
-                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#FFB4E8" }}></div>
+                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#afcbff" }}></div>
                     </label>
-                    <input type="radio" name="column-color" id="yellow" value="#f3ffe3" onClick={() => this.changeColumnColor("#f3ffe3")} />
+                    <input type="radio" name="column-color" id="yellow" value="#fff5ba" onClick={() => this.setNewColor("#fff5ba")} />
                     <label htmlFor="yellow">
-                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#FFB4E8" }}></div>
+                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#fff5ba" }}></div>
                     </label>
-                    <input type="radio" name="column-color" id="red" value="#ffc9de" onClick={() => this.changeColumnColor("#ffc9de")} />
+                    <input type="radio" name="column-color" id="red" value="#ffabab" onClick={() => this.setNewColor("#ffabab")} />
                     <label htmlFor="red">
-                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#FFB4E8" }}></div>
+                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#ffabab" }}></div>
                     </label>
-                    <input type="radio" name="column=color" id="none" value="#f1efeb" onClick={() => this.changeColumnColor("#f1efeb")} />
+                    <input type="radio" name="column=color" id="none" value="#f1efeb" onClick={() => this.setNewColor("#f1efeb")} />
                     <label htmlFor="none">
-                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#FFB4E8" }}></div>
+                        <div className="columnMenu-colorPicker" style={{ backgroundColor: "#f1efeb" }}></div>
                     </label>
                 </div>
             </div>
@@ -212,7 +218,7 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
                 <label>Key:</label>
                 <div className="collectionSchema-headerMenu-group">
                     <KeysDropdown
-                        keyValue={this.props.keyValue}
+                        keyValue={this.props.columnField.heading}
                         possibleKeys={this.props.possibleKeys}
                         existingKeys={this.props.existingKeys}
                         canAddNew={true}
@@ -225,9 +231,9 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
                     <>
                         {this.renderTypes()}
                         {this.renderSorting()}
-                        {this.renderColors()}
+                        {/* {this.renderColors()} */}
                         <div className="collectionSchema-headerMenu-group">
-                            <button onClick={() => this.props.deleteColumn(this.props.keyValue)}>Delete Column</button>
+                            <button onClick={() => this.props.deleteColumn(this.props.columnField.heading)}>Delete Column</button>
                         </div>
                     </>
                 }
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 749b9a364..487907c1c 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -167,8 +167,8 @@
         padding: 0;
         font-size: 13px;
         text-align: center;
-        
         // white-space: normal;
+        white-space: nowrap;
 
         .imageBox-cont {
             position: relative;
@@ -318,15 +318,19 @@ button.add-column {
     }
 
     .columnMenu-colors {
-
+        display: flex;
+        justify-content: space-between;
+        flex-wrap: wrap;
 
         input[type="radio"] {
             display: none;
         }
 
         .columnMenu-colorPicker {
+            cursor: pointer;
             width: 20px;
             height: 20px;
+            border-radius: 10px;
         }
     }
 }
@@ -335,13 +339,16 @@ button.add-column {
     // height: $MAX_ROW_HEIGHT;
     height: 100%;
     background-color: white;
+    // white-space: nowrap;
 
     &.row-focused .rt-tr {
         background-color: rgb(255, 246, 246);//$light-color-secondary;
     }
 
     &.row-wrapped {
-        white-space: normal;
+        .rt-td {
+            white-space: normal;
+        }
     }
 
     .row-dragger {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index ece638ec7..2ce6f1be3 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -280,16 +280,20 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @observable _focusedCell: { row: number, col: number } = { row: 0, col: 0 };
     @observable _sortedColumns: Map<string, { id: string, desc: boolean }> = new Map();
     @observable _openCollections: Array<string> = [];
-    @observable _textWrappedRows: Array<string> = [];
+    // @observable _textWrappedRows: Array<string> = [];
     @observable private _node: HTMLDivElement | null = null;
 
     @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); }
     @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; }
     @computed get tableWidth() { return this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH - this.previewWidth(); }
+
     @computed get columns() {
-        console.log("columns");
         return Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField), []);
     }
+    set columns(columns: SchemaHeaderField[]) {
+        this.props.Document.schemaColumns = new List<SchemaHeaderField>(columns);
+    }
+
     @computed get childDocs() {
         if (this.props.childDocs) return this.props.childDocs;
 
@@ -300,7 +304,14 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
         doc[this.props.fieldKey] = new List<Doc>(docs);
     }
-    set columns(columns: SchemaHeaderField[]) { this.props.Document.schemaColumns = new List<SchemaHeaderField>(columns); }
+
+    @computed get textWrappedRows() {
+        return Cast(this.props.Document.textwrappedSchemaRows, listSpec("string"), []);
+    }
+    set textWrappedRows(textWrappedRows: string[]) {
+        this.props.Document.textwrappedSchemaRows = new List<string>(textWrappedRows);
+    }
+
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
         let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.heading.toUpperCase() === key.toUpperCase()) === -1);
@@ -345,6 +356,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                 setColumnType={this.setColumnType}
                 setColumnSort={this.setColumnSort}
                 removeColumnSort={this.removeColumnSort}
+                setColumnColor={this.setColumnColor}
             />;
 
             return {
@@ -399,19 +411,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         return 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;  
-    // }
     constructor(props: SchemaTableProps) {
         super(props);
         // convert old schema columns (list of strings) into new schema columns (list of schema header fields)
@@ -436,8 +435,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     tableRemoveDoc = (document: Doc): boolean => {
-        // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
+
         let children = this.childDocs;
         if (children.indexOf(document) !== -1) {
             children.splice(children.indexOf(document), 1);
@@ -456,11 +454,10 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             ScreenToLocalTransform: this.props.ScreenToLocalTransform,
             addDoc: this.tableAddDoc,
             removeDoc: this.tableRemoveDoc,
-            // removeDoc: this.props.deleteDocument,
             rowInfo,
             rowFocused: !this._headerIsEditing && rowInfo.index === this._focusedCell.row && this.props.isFocused(this.props.Document),
-            textWrapRow: this.textWrapRow,
-            rowWrapped: this._textWrappedRows.findIndex(id => rowInfo.original[Id] === id) > -1
+            textWrapRow: this.toggleTextWrapRow,
+            rowWrapped: this.textWrappedRows.findIndex(id => rowInfo.original[Id] === id) > -1
         };
     }
 
@@ -471,9 +468,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let row = rowInfo.index;
         //@ts-ignore
         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!);
         return {
             style: {
                 border: !this._headerIsEditing && isFocused ? "2px solid rgb(255, 160, 160)" : "1px solid #f1efeb"
@@ -481,19 +476,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         };
     }
 
-    // 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)) {
-    //     } else {
-    //         this._isOpen = false;
-    //         this.props.setIsEditing(false);
-    //     }
-    // }
-
     @action
     onExpandCollection = (collection: Doc): void => {
         this._openCollections.push(collection[Id]);
@@ -533,8 +515,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : "";
             this.changeFocusedCellByDirection(direction);
 
-            // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-            // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
             let children = this.childDocs;
             const pdoc = FieldValue(children[this._focusedCell.row]);
             pdoc && this.props.setPreviewDoc(pdoc);
@@ -543,8 +523,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @action
     changeFocusedCellByDirection = (direction: string): void => {
-        // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
         let children = this.childDocs;
         switch (direction) {
             case "tab":
@@ -569,81 +547,74 @@ 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);
     }
 
     @action
     changeFocusedCellByIndex = (row: number, col: number): void => {
-        // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
-
         this._focusedCell = { row: row, col: col };
         this.props.setFocused(this.props.Document);
-
-        // const fdoc = FieldValue(children[this._focusedCell.row]);
-        // fdoc && this.props.setPreviewDoc(fdoc);
     }
 
     createRow = () => {
-        // let doc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        // let children = Cast(doc[this.props.fieldKey], listSpec(Doc), []);
         let children = this.childDocs;
 
         let newDoc = Docs.Create.TextDocument({ width: 100, height: 30 });
         let proto = Doc.GetProto(newDoc);
         proto.title = "";
         children.push(newDoc);
+
         this.childDocs = children;
     }
 
     @action
     createColumn = () => {
         let index = 0;
-        let found = this.columns.findIndex(col => col.heading.toUpperCase() === "New field".toUpperCase()) > -1;
+        let columns = this.columns;
+        let found = columns.findIndex(col => col.heading.toUpperCase() === "New field".toUpperCase()) > -1;
         if (!found) {
-            console.log("create column found");
-            this.columns.push(new SchemaHeaderField("New field", "#f1efeb"));
+            columns.push(new SchemaHeaderField("New field", "#f1efeb"));
+            this.columns = columns;
             return;
         }
         while (found) {
             index++;
-            found = this.columns.findIndex(col => col.heading.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1;
+            found = columns.findIndex(col => col.heading.toUpperCase() === ("New field (" + index + ")").toUpperCase()) > -1;
         }
-        console.log("create column new");
-        this.columns.push(new SchemaHeaderField("New field (" + index + ")", "#f1efeb"));
+        columns.push(new SchemaHeaderField("New field (" + index + ")", "#f1efeb"));
+        this.columns = columns;
     }
 
     @action
     deleteColumn = (key: string) => {
-        console.log("deleting columnnn");
-        let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField));
-        if (list === undefined) {
-            console.log("delete column");
-            this.props.Document.schemaColumns = list = new List<SchemaHeaderField>([]);
+        let columns = this.columns;
+        // let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField));
+        if (columns === undefined) {
+            this.columns = new List<SchemaHeaderField>([]);
         } else {
-            const index = list.map(c => c.heading).indexOf(key);
+            const index = columns.map(c => c.heading).indexOf(key);
             if (index > -1) {
-                list.splice(index, 1);
+                columns.splice(index, 1);
+                this.columns = columns;
             }
         }
     }
 
     @action
     changeColumns = (oldKey: string, newKey: string, addNew: boolean) => {
-        console.log("changingin columnsdfhs");
-        let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField));
-        if (list === undefined) {
-            console.log("change columns new");
-            this.props.Document.schemaColumns = list = new List<SchemaHeaderField>([new SchemaHeaderField(newKey, "#f1efeb")]);
+        // let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField));
+        let columns = this.columns;
+        if (columns === undefined) {
+            // console.log("change columns new");
+            this.columns = new List<SchemaHeaderField>([new SchemaHeaderField(newKey, "f1efeb")]);
         } else {
-            console.log("change column");
             if (addNew) {
-                this.columns.push(new SchemaHeaderField(newKey, "#f1efeb"));
+                columns.push(new SchemaHeaderField(newKey, "f1efeb"));
+                this.columns = columns;
             } else {
-                const index = list.map(c => c.heading).indexOf(oldKey);
+                const index = columns.map(c => c.heading).indexOf(oldKey);
                 if (index > -1) {
-                    list[index] = new SchemaHeaderField(newKey, "#f1efeb");
+                    columns[index] = new SchemaHeaderField(newKey, columns[index].color);
+                    this.columns = columns;
                 }
             }
         }
@@ -667,16 +638,39 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         return NumCast(typesDoc[column.heading]);
     }
 
-    setColumnType = (key: string, type: ColumnType): void => {
-        if (columnTypes.get(key)) return;
-        const typesDoc = FieldValue(Cast(this.props.Document.schemaColumnTypes, Doc));
-        if (!typesDoc) {
-            let newTypesDoc = new Doc();
-            newTypesDoc[key] = type;
-            this.props.Document.schemaColumnTypes = newTypesDoc;
-            return;
-        } else {
-            typesDoc[key] = type;
+    setColumnType = (columnField: SchemaHeaderField, type: ColumnType): void => {
+        if (columnTypes.get(columnField.heading)) return;
+
+        let columns = this.columns;
+        let index = columns.indexOf(columnField);
+        if (index > -1) {
+            // let column = columns[index];
+            columnField.type = NumCast(type);
+            columns[index] = columnField;
+            this.columns = columns;
+        }
+
+        // const typesDoc = FieldValue(Cast(this.props.Document.schemaColumnTypes, Doc));
+        // if (!typesDoc) {
+        //     let newTypesDoc = new Doc();
+        //     newTypesDoc[key] = type;
+        //     this.props.Document.schemaColumnTypes = newTypesDoc;
+        //     return;
+        // } else {
+        //     typesDoc[key] = type;
+        // }
+    }
+
+    setColumnColor = (columnField: SchemaHeaderField, color: string): void => {
+        // console.log("setting color", key);
+        let columns = this.columns;
+        let index = columns.indexOf(columnField);
+        if (index > -1) {
+            // let column = columns[index];
+            columnField.color = color;
+            columns[index] = columnField;
+            this.columns = columns;
+            console.log(columnField, this.columns[index]);
         }
     }
 
@@ -694,7 +688,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         if (oldIndex === newIndex) return;
 
         columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]);
-        this.setColumns(columns);
+        this.columns = columns;
+        // this.setColumns(columns);
     }
 
     @action
@@ -725,14 +720,18 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     @action
-    textWrapRow = (doc: Doc): void => {
-        let index = this._textWrappedRows.findIndex(id => doc[Id] === id);
+    toggleTextWrapRow = (doc: Doc): void => {
+        let textWrapped = this.textWrappedRows;
+        let index = textWrapped.findIndex(id => doc[Id] === id);
+        console.log("toggle text wrap", index);
+
         if (index > -1) {
-            this._textWrappedRows.splice(index, 1);
+            textWrapped.splice(index, 1);
         } else {
-            this._textWrappedRows.push(doc[Id]);
+            textWrapped.push(doc[Id]);
         }
 
+        this.textWrappedRows = textWrapped;
     }
 
     @computed
@@ -748,7 +747,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let expanded = {};
         //@ts-ignore
         expandedRowsList.forEach(row => expanded[row] = true);
-        console.log(...[...this._textWrappedRows]); // TODO: get component to rerender on text wrap change without needign to console.log :((((
+        console.log("text wrapped rows", ...[...this.textWrappedRows]); // TODO: get component to rerender on text wrap change without needign to console.log :((((
 
         return <ReactTable
             style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }}
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 2bffe3cc0..8691bea8a 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -17,6 +17,9 @@ import { CompileScript } from "../../util/Scripting";
 import { ScriptField } from "../../../new_fields/ScriptField";
 import { CollectionSchemaView } from "./CollectionSchemaView";
 import { COLLECTION_BORDER_WIDTH } from "../globalCssVariables.scss";
+import { listSpec } from "../../../new_fields/Schema";
+import { List } from "../../../new_fields/List";
+import { Id } from "../../../new_fields/FieldSymbols";
 const datepicker = require('js-datepicker');
 
 interface CollectionViewChromeProps {
@@ -365,6 +368,7 @@ export class CollectionStackingViewChrome extends React.Component<CollectionView
 
 @observer
 export class CollectionSchemaViewChrome extends React.Component<CollectionViewChromeProps> {
+    // private _textwrapAllRows: boolean = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
 
     togglePreview = () => {
         let dividerWidth = 4;
@@ -373,14 +377,43 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionViewCh
         let previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth);
         let tableWidth = panelWidth - 2 * borderWidth - dividerWidth - previewWidth;
         this.props.CollectionView.props.Document.schemaPreviewWidth = previewWidth === 0 ? Math.min(tableWidth / 3, 200) : 0;
+    }
 
+    @action
+    toggleTextwrap = async () => {
+        console.log("toggle text wrap");
+        let textwrappedRows = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []);
+        if (textwrappedRows.length) {
+            console.log("unwrap");
+            this.props.CollectionView.props.Document.textwrappedSchemaRows = new List<string>([]);
+        } else {
+            console.log("wrap");
+            let docs: Doc | Doc[] | Promise<Doc> | Promise<Doc[]> | (() => DocLike)
+                = () => DocListCast(this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldExt ? this.props.CollectionView.props.fieldExt : this.props.CollectionView.props.fieldKey]);
+            if (typeof docs === "function") {
+                docs = docs();
+            }
+            docs = await docs;
+            if (docs instanceof Doc) {
+                let allRows = [docs[Id]];
+                console.log(...[...allRows]);
+                this.props.CollectionView.props.Document.textwrappedSchemaRows = new List<string>(allRows);
+            } else {
+                let allRows = docs.map(doc => doc[Id]);
+                console.log(...[...allRows]);
+                this.props.CollectionView.props.Document.textwrappedSchemaRows = new List<string>(allRows);
+            }
+        }
     }
 
 
     render() {
         let previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth);
+        let textWrapped = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
+
         return (
             <div className="collectionStackingViewChrome-cont">
+                <div id=""><input type="checkbox" key={"Toggle textwrap"} checked={textWrapped} onChange={this.toggleTextwrap} />Textwrap</div>
                 <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={previewWidth !== 0} onChange={this.togglePreview} />Show Preview</div>
             </div>
         );
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 7decadbe9..476a0f957 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -135,7 +135,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 doc.width = 200;
                 docList.push(doc);
             }
-            let newCol = Docs.Create.SchemaDocument([...(groupAttr ? [new SchemaHeaderField("_group", "#f1efeb")] : []), ...columns.filter(c => c).map(c => new SchemaHeaderField(c))], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 });
+            let newCol = Docs.Create.SchemaDocument([...(groupAttr ? [new SchemaHeaderField("_group", "#f1efeb")] : []), ...columns.filter(c => c).map(c => new SchemaHeaderField(c, "#f1efeb"))], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 });
 
             this.props.addDocument(newCol, false);
         }
diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts
index 475296d5c..9f716bf9f 100644
--- a/src/new_fields/SchemaHeaderField.ts
+++ b/src/new_fields/SchemaHeaderField.ts
@@ -6,7 +6,7 @@ import { scriptingGlobal, Scripting } from "../client/util/Scripting";
 import { ColumnType } from "../client/views/collections/CollectionSchemaView";
 
 export const PastelSchemaPalette = new Map<string, string>([
-    ["pink1", "#FFB4E8"],
+    // ["pink1", "#FFB4E8"],
     ["pink2", "#ff9cee"],
     ["pink3", "#ffccf9"],
     ["pink4", "#fcc2ff"],
@@ -32,7 +32,7 @@ export const PastelSchemaPalette = new Map<string, string>([
     ["yellow2", "#e7ffac"],
     ["yellow3", "#ffffd1"],
     ["yellow4", "#fff5ba"],
-    ["red1", "#ffc9de"],
+    // ["red1", "#ffc9de"],
     ["red2", "#ffabab"],
     ["red3", "#ffbebc"],
     ["red4", "#ffcbc1"],
@@ -45,15 +45,16 @@ export const RandomPastel = () => Array.from(PastelSchemaPalette.values())[Math.
 export class SchemaHeaderField extends ObjectField {
     @serializable(primitive())
     heading: string;
+    @serializable(primitive())
     color: string;
+    @serializable(primitive())
     type: number;
 
-    constructor(heading: string = "", color: string, type?: ColumnType) {
-        console.log("CREATING SCHEMA HEADER FIELD");
+    constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType) {
         super();
 
         this.heading = heading;
-        this.color = color === undefined ? "#000" : color;
+        this.color = color;
         if (type) {
             this.type = type;
         }
-- 
cgit v1.2.3-70-g09d2


From ae3e8e1497eb172d80b12cfc980a10486adabd8b Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 29 Jul 2019 19:22:02 -0400
Subject: fixed templates with stacking and other nested views.

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

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 996118c00..08ab22725 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -233,6 +233,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     }
 
     render() {
+        Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey);
         // 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 (
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 6e1968774..bcf3a85d7 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -276,6 +276,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             SetValue: this.addGroup,
             contents: "+ ADD A GROUP"
         };
+        Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey);
+
         // let uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
         return (
             <div className="collectionStackingView"
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index b045869b7..b1e6eada0 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -572,6 +572,7 @@ export class CollectionTreeView extends CollectionSubView(Document) {
 
 
     render() {
+        Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey);
         let dropAction = StrCast(this.props.Document.dropAction) as dropActionType;
         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);
-- 
cgit v1.2.3-70-g09d2


From 5d1135faa9506ed136b2fa0d298e23fd07ca8c1f Mon Sep 17 00:00:00 2001
From: fawn <fangrui_tong@brown.edu>
Date: Mon, 29 Jul 2019 21:41:56 -0400
Subject: schema preview in right position again

---
 .../views/collections/CollectionSchemaView.scss    | 27 ++++++++++--
 .../views/collections/CollectionSchemaView.tsx     | 48 ++++++++--------------
 2 files changed, 41 insertions(+), 34 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index c1d25f437..dc6ca060d 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -13,9 +13,12 @@
     // overflow: hidden;
     // overflow-x: scroll;
     // border: none;
-    overflow: scroll;
+    // overflow: scroll;
     // overflow-y: scroll;
     transition: top 0.5s;
+    display: flex;
+    justify-content: space-between;
+    flex-wrap: nowrap;
 
     // .collectionSchemaView-cellContents {
     //     height: $MAX_ROW_HEIGHT;
@@ -26,10 +29,16 @@
     //     }
     // }
 
+    .collectionSchemaView-tableContainer {
+        width: 100%;
+        height: 100%;
+        overflow: scroll;
+    }
+
     .collectionSchemaView-previewRegion {
         position: relative;
         background: $light-color;
-        float: left;
+        // float: left;
         height: 100%;
 
         .collectionSchemaView-previewDoc {
@@ -53,7 +62,7 @@
 
     .collectionSchemaView-dividerDragger {
         position: relative;
-        float: left;
+        // float: left;
         height: 100%;
         width: 20px;
         z-index: 20;
@@ -74,6 +83,7 @@
     background: white;
     box-sizing: border-box;
     border: none !important;
+    float: none !important;
 
     .rt-table {
         // overflow-y: auto;
@@ -526,4 +536,15 @@ button.add-column {
         left: 50%;
         transform: translate(-50%, -50%);
     }
+}
+
+.collectionSchemaView-addRow {
+    color: gray;
+    letter-spacing: 2px;
+    text-transform: uppercase;
+    cursor: pointer;
+    font-size: 10.5px;
+    padding: 10px;
+    margin-left: 50px;
+    margin-top: 10px;
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 2ce6f1be3..0f9c9ca51 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -122,8 +122,14 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @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]);
+        console.log("divider", nativeWidth.right - nativeWidth.left, this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]);
+        let minWidth = 40;
+        let maxWidth = 1000;
+        let movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0];
+        let width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth;
+        this.props.Document.schemaPreviewWidth = width;
+        // 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 => {
@@ -237,9 +243,10 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         // if (SelectionManager.SelectedDocuments().length > 0) console.log(StrCast(SelectionManager.SelectedDocuments()[0].Document.title));
         // if (DocumentManager.Instance.getDocumentView(this.props.Document)) console.log(StrCast(this.props.Document.title), SelectionManager.IsSelected(DocumentManager.Instance.getDocumentView(this.props.Document)!))
         return (
-            <div className="collectionSchemaView-container" style={{ height: this.chromeCollapsed ? "100%" : "calc(100% - 70px" }}
-                onPointerDown={this.onPointerDown} onWheel={this.onWheel} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createTarget}>
-                {this.schemaTable}
+            <div className="collectionSchemaView-container" style={{ height: this.chromeCollapsed ? "100%" : "calc(100% - 70px" }}>
+                <div className="collectionSchemaView-tableContainer" onPointerDown={this.onPointerDown} onWheel={this.onWheel} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createTarget}>
+                    {this.schemaTable}
+                </div>
                 {this.dividerDragger}
                 {!this.previewWidth() ? (null) : this.previewPanel}
             </div>
@@ -280,8 +287,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @observable _focusedCell: { row: number, col: number } = { row: 0, col: 0 };
     @observable _sortedColumns: Map<string, { id: string, desc: boolean }> = new Map();
     @observable _openCollections: Array<string> = [];
-    // @observable _textWrappedRows: Array<string> = [];
-    @observable private _node: HTMLDivElement | null = null;
 
     @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); }
     @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; }
@@ -321,8 +326,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let focusedCol = this._focusedCell.col;
         let isEditable = !this._headerIsEditing;// && this.props.isSelected();
 
-        // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        // let children = DocListCast(cdoc[this.props.fieldKey]);
         let children = this.childDocs;
 
         if (children.reduce((found, doc) => found || doc.type === "collection", false)) {
@@ -587,7 +590,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @action
     deleteColumn = (key: string) => {
         let columns = this.columns;
-        // let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField));
         if (columns === undefined) {
             this.columns = new List<SchemaHeaderField>([]);
         } else {
@@ -601,10 +603,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @action
     changeColumns = (oldKey: string, newKey: string, addNew: boolean) => {
-        // let list = Cast(this.props.Document.schemaColumns, listSpec(SchemaHeaderField));
         let columns = this.columns;
         if (columns === undefined) {
-            // console.log("change columns new");
             this.columns = new List<SchemaHeaderField>([new SchemaHeaderField(newKey, "f1efeb")]);
         } else {
             if (addNew) {
@@ -689,7 +689,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
         columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]);
         this.columns = columns;
-        // this.setColumns(columns);
     }
 
     @action
@@ -703,9 +702,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     get documentKeys() {
-        const docs = DocListCast(this.props.Document[this.props.fieldKey]);
-
-        // let docs = this.childDocs;
+        let docs = this.childDocs;
         let keys: { [key: string]: boolean } = {};
         // bcz: ugh.  this is untracked since otherwise a large collection of documents will blast the server for all their fields.
         //  then as each document's fields come back, we update the documents _proxies.  Each time we do this, the whole schema will be
@@ -736,12 +733,10 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @computed
     get reactTable() {
-
-        // let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        // let children = DocListCast(cdoc[this.props.fieldKey]);
         let children = this.childDocs;
 
         let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
+        console.log(previewWidth);
         let hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false);
         let expandedRowsList = this._openCollections.map(col => children.findIndex(doc => doc[Id] === col).toString());
         let expanded = {};
@@ -750,7 +745,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         console.log("text wrapped rows", ...[...this.textWrappedRows]); // TODO: get component to rerender on text wrap change without needign to console.log :((((
 
         return <ReactTable
-            style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }}
+            style={{ position: "relative" }}
             data={children}
             page={0}
             pageSize={children.length}
@@ -765,7 +760,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             SubComponent={hasCollectionChild ?
                 row => {
                     if (row.original.type === "collection") {
-                        // let childDocs = DocListCast(row.original[this.props.fieldKey]);
                         return <div className="sub"><SchemaTable {...this.props} Document={row.original} childDocs={undefined} /></div>;
                     }
                 }
@@ -785,8 +779,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let csv: string = this.columns.reduce((val, col) => val + col + ",", "");
         csv = csv.substr(0, csv.length - 1) + "\n";
         let self = this;
-        let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        // let children = DocListCast(cdoc[this.props.fieldKey]);
         this.childDocs.map(doc => {
             csv += self.columns.reduce((val, col) => val + (doc[col.heading] ? doc[col.heading]!.toString() : "0") + ",", "");
             csv = csv.substr(0, csv.length - 1) + "\n";
@@ -804,11 +796,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     getField = (row: number, col?: number) => {
-        // const docs = DocListCast(this.props.Document[this.props.fieldKey]);
-
-        let cdoc = this.props.dataDoc ? this.props.dataDoc : this.props.Document;
-        const docs = DocListCast(cdoc[this.props.fieldKey]);
-        // let docs = this.childDocs;
+        let docs = this.childDocs;
 
         row = row % docs.length;
         while (row < 0) row += docs.length;
@@ -880,13 +868,11 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     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 (
             <div className="collectionSchemaView-table" onPointerDown={this.onPointerDown} onWheel={this.onWheel}
                 onDrop={(e: React.DragEvent) => this.props.onDrop(e, {})} onContextMenu={this.onContextMenu} >
                 {this.reactTable}
-                <button onClick={() => this.createRow()}>new row</button>
+                <div className="collectionSchemaView-addRow" onClick={() => this.createRow()}>+ new</div>
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From 6efe31636305bf5120d472f456b69d1b699b2ae8 Mon Sep 17 00:00:00 2001
From: fawn <fangrui_tong@brown.edu>
Date: Mon, 29 Jul 2019 22:48:31 -0400
Subject: styled toggle buttons on schema chrome

---
 .../views/collections/CollectionSchemaView.scss    |  3 +-
 .../views/collections/CollectionSchemaView.tsx     |  6 ---
 .../views/collections/CollectionViewChromes.scss   | 51 ++++++++++++++++++++++
 .../views/collections/CollectionViewChromes.tsx    | 29 ++++++++----
 4 files changed, 73 insertions(+), 16 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index dc6ca060d..e826ff63a 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -492,7 +492,8 @@ button.add-column {
 }
 
 .collectionSchemaView-table {
-    width: calc(100% - 7px);
+    // width: calc(100% - 7px);
+    width: 100%;
     height: 100%;
     // overflow-y: scroll;
     overflow: visible;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 0f9c9ca51..26b19474a 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -122,7 +122,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @action
     onDividerMove = (e: PointerEvent): void => {
         let nativeWidth = this._mainCont!.getBoundingClientRect();
-        console.log("divider", nativeWidth.right - nativeWidth.left, this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]);
         let minWidth = 40;
         let maxWidth = 1000;
         let movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0];
@@ -240,8 +239,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     }
 
     render() {
-        // if (SelectionManager.SelectedDocuments().length > 0) console.log(StrCast(SelectionManager.SelectedDocuments()[0].Document.title));
-        // if (DocumentManager.Instance.getDocumentView(this.props.Document)) console.log(StrCast(this.props.Document.title), SelectionManager.IsSelected(DocumentManager.Instance.getDocumentView(this.props.Document)!))
         return (
             <div className="collectionSchemaView-container" style={{ height: this.chromeCollapsed ? "100%" : "calc(100% - 70px" }}>
                 <div className="collectionSchemaView-tableContainer" onPointerDown={this.onPointerDown} onWheel={this.onWheel} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createTarget}>
@@ -419,7 +416,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         // 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 && typeof oldSchemaColumns[0] !== "object") {
-            console.log("REMAKING COLUMNs");
             let newSchemaColumns = oldSchemaColumns.map(i => typeof i === "string" ? new SchemaHeaderField(i, "#f1efeb") : i);
             this.props.Document.schemaColumns = new List<SchemaHeaderField>(newSchemaColumns);
         }
@@ -720,7 +716,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     toggleTextWrapRow = (doc: Doc): void => {
         let textWrapped = this.textWrappedRows;
         let index = textWrapped.findIndex(id => doc[Id] === id);
-        console.log("toggle text wrap", index);
 
         if (index > -1) {
             textWrapped.splice(index, 1);
@@ -736,7 +731,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let children = this.childDocs;
 
         let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
-        console.log(previewWidth);
         let hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false);
         let expandedRowsList = this._openCollections.map(col => children.findIndex(doc => doc[Id] === col).toString());
         let expanded = {};
diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss
index f9f3ce473..933ba7411 100644
--- a/src/client/views/collections/CollectionViewChromes.scss
+++ b/src/client/views/collections/CollectionViewChromes.scss
@@ -165,4 +165,55 @@
             cursor: text;
         }
     }
+}
+
+.collectionSchemaViewChrome-cont {
+    display: flex;
+    font-size: 10.5px;
+
+    .collectionSchemaViewChrome-toggle {
+        display: flex;
+        margin-left: 10px;
+    }
+
+    .collectionSchemaViewChrome-label {
+        text-transform: uppercase;
+        letter-spacing: 2px;
+        margin-right: 5px;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+    }
+
+    .collectionSchemaViewChrome-toggler {
+        width: 100px;
+        height: 41px;
+        background-color: black;
+        position: relative;
+    }
+
+    .collectionSchemaViewChrome-togglerButton {
+        width: 47px;
+        height: 35px;
+        background-color: lightgray;
+        // position: absolute;
+        transition: all 0.5s ease;
+        // top: 3px;
+        margin-top: 3px;
+        color: gray;
+        letter-spacing: 2px;
+        text-transform: uppercase;
+        display: flex;
+        flex-direction: column;
+        justify-content: center;
+        text-align: center;
+
+        &.on {
+            margin-left: 3px;
+        }
+
+        &.off {
+            margin-left: 50px;
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 8691bea8a..92afb3888 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -20,6 +20,7 @@ import { COLLECTION_BORDER_WIDTH } from "../globalCssVariables.scss";
 import { listSpec } from "../../../new_fields/Schema";
 import { List } from "../../../new_fields/List";
 import { Id } from "../../../new_fields/FieldSymbols";
+import { threadId } from "worker_threads";
 const datepicker = require('js-datepicker');
 
 interface CollectionViewChromeProps {
@@ -381,13 +382,10 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionViewCh
 
     @action
     toggleTextwrap = async () => {
-        console.log("toggle text wrap");
         let textwrappedRows = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []);
         if (textwrappedRows.length) {
-            console.log("unwrap");
             this.props.CollectionView.props.Document.textwrappedSchemaRows = new List<string>([]);
         } else {
-            console.log("wrap");
             let docs: Doc | Doc[] | Promise<Doc> | Promise<Doc[]> | (() => DocLike)
                 = () => DocListCast(this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldExt ? this.props.CollectionView.props.fieldExt : this.props.CollectionView.props.fieldKey]);
             if (typeof docs === "function") {
@@ -396,11 +394,9 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionViewCh
             docs = await docs;
             if (docs instanceof Doc) {
                 let allRows = [docs[Id]];
-                console.log(...[...allRows]);
                 this.props.CollectionView.props.Document.textwrappedSchemaRows = new List<string>(allRows);
             } else {
                 let allRows = docs.map(doc => doc[Id]);
-                console.log(...[...allRows]);
                 this.props.CollectionView.props.Document.textwrappedSchemaRows = new List<string>(allRows);
             }
         }
@@ -412,10 +408,25 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionViewCh
         let textWrapped = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
 
         return (
-            <div className="collectionStackingViewChrome-cont">
-                <div id=""><input type="checkbox" key={"Toggle textwrap"} checked={textWrapped} onChange={this.toggleTextwrap} />Textwrap</div>
-                <div id="preview-schema-checkbox-div"><input type="checkbox" key={"Show Preview"} checked={previewWidth !== 0} onChange={this.togglePreview} />Show Preview</div>
-            </div>
+            <div className="collectionSchemaViewChrome-cont">
+                <div className="collectionSchemaViewChrome-toggle">
+                    <div className="collectionSchemaViewChrome-label">Wrap Text: </div>
+                    <div className="collectionSchemaViewChrome-toggler" onClick={this.toggleTextwrap}>
+                        <div className={"collectionSchemaViewChrome-togglerButton" + (textWrapped ? " on" : " off")}>
+                            {textWrapped ? "on" : "off"}
+                        </div>
+                    </div>
+                </div>
+
+                <div className="collectionSchemaViewChrome-toggle">
+                    <div className="collectionSchemaViewChrome-label">Show Preview: </div>
+                    <div className="collectionSchemaViewChrome-toggler" onClick={this.togglePreview}>
+                        <div className={"collectionSchemaViewChrome-togglerButton" + (previewWidth !== 0 ? " on" : " off")}>
+                            {previewWidth !== 0 ? "on" : "off"}
+                        </div>
+                    </div>
+                </div>
+            </div >
         );
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


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

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

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

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


From dd5d7503e05962fa9a22baa9f5fa00373393ac11 Mon Sep 17 00:00:00 2001
From: fawn <fangrui_tong@brown.edu>
Date: Tue, 30 Jul 2019 15:52:32 -0400
Subject: schema column menu stylign

---
 .../views/collections/CollectionSchemaHeaders.tsx  | 68 +++++++++++------
 .../views/collections/CollectionSchemaView.scss    | 85 +++++++++++++---------
 .../views/collections/CollectionSchemaView.tsx     | 11 +--
 src/new_fields/SchemaHeaderField.ts                |  2 +-
 4 files changed, 103 insertions(+), 63 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index 84132ef2e..62762962e 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -2,7 +2,7 @@ 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, faToggleOn } from '@fortawesome/free-solid-svg-icons';
+import { faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faSortAmountDown, faSortAmountUp, faTimes } 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";
@@ -12,7 +12,7 @@ import { contains } from "typescript-collections/dist/lib/arrays";
 import { faFile } from "@fortawesome/free-regular-svg-icons";
 import { SchemaHeaderField, RandomPastel, PastelSchemaPalette } from "../../../new_fields/SchemaHeaderField";
 
-library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faFile);
+library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faFile, faSortAmountDown, faSortAmountUp, faTimes);
 
 export interface HeaderProps {
     keyValue: SchemaHeaderField;
@@ -136,25 +136,32 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
 
     renderTypes = () => {
         if (this.props.typeConst) return <></>;
+
+        let type = this.props.columnField.type;
         return (
             <div className="collectionSchema-headerMenu-group">
                 <label>Column type:</label>
                 <div className="columnMenu-types">
-                    <button title="Any" className={this.props.columnField.type === ColumnType.Any ? "active" : ""} onClick={() => this.changeColumnType(ColumnType.Any)}>
+                    <div className={"columnMenu-option" + (type === ColumnType.Any ? " active" : "")} onClick={() => this.changeColumnType(ColumnType.Any)}>
                         <FontAwesomeIcon icon={"align-justify"} size="sm" />
-                    </button>
-                    <button title="Number" className={this.props.columnField.type === ColumnType.Number ? "active" : ""} onClick={() => this.changeColumnType(ColumnType.Number)}>
+                        Any
+                    </div>
+                    <div className={"columnMenu-option" + (type === ColumnType.Number ? " active" : "")} onClick={() => this.changeColumnType(ColumnType.Number)}>
                         <FontAwesomeIcon icon={"hashtag"} size="sm" />
-                    </button>
-                    <button title="String" className={this.props.columnField.type === ColumnType.String ? "active" : ""} onClick={() => this.changeColumnType(ColumnType.String)}>
+                        Number
+                    </div>
+                    <div className={"columnMenu-option" + (type === ColumnType.String ? " active" : "")} onClick={() => this.changeColumnType(ColumnType.String)}>
                         <FontAwesomeIcon icon={"font"} size="sm" />
-                    </button>
-                    <button title="Checkbox" className={this.props.columnField.type === ColumnType.Boolean ? "active" : ""} onClick={() => this.changeColumnType(ColumnType.Boolean)}>
+                        Text
+                    </div>
+                    <div className={"columnMenu-option" + (type === ColumnType.Boolean ? " active" : "")} onClick={() => this.changeColumnType(ColumnType.Boolean)}>
                         <FontAwesomeIcon icon={"check-square"} size="sm" />
-                    </button>
-                    <button title="Document" className={this.props.columnField.type === ColumnType.Doc ? "active" : ""} onClick={() => this.changeColumnType(ColumnType.Doc)}>
+                        Checkbox
+                    </div>
+                    <div className={"columnMenu-option" + (type === ColumnType.Doc ? " active" : "")} onClick={() => this.changeColumnType(ColumnType.Doc)}>
                         <FontAwesomeIcon icon={"file"} size="sm" />
-                    </button>
+                        Document
+                    </div>
                 </div>
             </div >
         );
@@ -165,9 +172,18 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
             <div className="collectionSchema-headerMenu-group">
                 <label>Sort by:</label>
                 <div className="columnMenu-sort">
-                    <div className="columnMenu-option" onClick={() => this.props.setColumnSort(this.props.columnField.heading, false)}>Sort ascending</div>
-                    <div className="columnMenu-option" onClick={() => this.props.setColumnSort(this.props.columnField.heading, true)}>Sort descending</div>
-                    <div className="columnMenu-option" onClick={() => this.props.removeColumnSort(this.props.columnField.heading)}>Clear sorting</div>
+                    <div className="columnMenu-option" onClick={() => this.props.setColumnSort(this.props.columnField.heading, true)}>
+                        <FontAwesomeIcon icon="sort-amount-down" size="sm" />
+                        Sort descending
+                    </div>
+                    <div className="columnMenu-option" onClick={() => this.props.setColumnSort(this.props.columnField.heading, false)}>
+                        <FontAwesomeIcon icon="sort-amount-up" size="sm" />
+                        Sort ascending
+                    </div>
+                    <div className="columnMenu-option" onClick={() => this.props.removeColumnSort(this.props.columnField.heading)}>
+                        <FontAwesomeIcon icon="times" size="sm" />
+                        Clear sorting
+                    </div>
                 </div>
             </div>
         );
@@ -175,16 +191,24 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
 
     renderColors = () => {
         let selected = this.props.columnField.color;
+
+        let pink = PastelSchemaPalette.get("pink2");
+        let purple = PastelSchemaPalette.get("purple2");
+        let blue = PastelSchemaPalette.get("bluegreen1");
+        let yellow = PastelSchemaPalette.get("yellow4");
+        let red = PastelSchemaPalette.get("red2");
+        let gray = "#f1efeb";
+
         return (
             <div className="collectionSchema-headerMenu-group">
                 <label>Color:</label>
                 <div className="columnMenu-colors">
-                    <div className={"columnMenu-colorPicker" + (selected === "#FFB4E8" ? " active" : "")} style={{ backgroundColor: "#FFB4E8" }} onClick={() => this.changeColumnColor("#FFB4E8")}></div>
-                    <div className={"columnMenu-colorPicker" + (selected === "#b28dff" ? " active" : "")} style={{ backgroundColor: "#b28dff" }} onClick={() => this.changeColumnColor("#b28dff")}></div>
-                    <div className={"columnMenu-colorPicker" + (selected === "#afcbff" ? " active" : "")} style={{ backgroundColor: "#afcbff" }} onClick={() => this.changeColumnColor("#afcbff")}></div>
-                    <div className={"columnMenu-colorPicker" + (selected === "#fff5ba" ? " active" : "")} style={{ backgroundColor: "#fff5ba" }} onClick={() => this.changeColumnColor("#fff5ba")}></div>
-                    <div className={"columnMenu-colorPicker" + (selected === "#ffabab" ? " active" : "")} style={{ backgroundColor: "#ffabab" }} onClick={() => this.changeColumnColor("#ffabab")}></div>
-                    <div className={"columnMenu-colorPicker" + (selected === "#f1efeb" ? " active" : "")} style={{ backgroundColor: "#f1efeb" }} onClick={() => this.changeColumnColor("#f1efeb")}></div>
+                    <div className={"columnMenu-colorPicker" + (selected === pink ? " active" : "")} style={{ backgroundColor: pink }} onClick={() => this.changeColumnColor(pink!)}></div>
+                    <div className={"columnMenu-colorPicker" + (selected === purple ? " active" : "")} style={{ backgroundColor: purple }} onClick={() => this.changeColumnColor(purple!)}></div>
+                    <div className={"columnMenu-colorPicker" + (selected === blue ? " active" : "")} style={{ backgroundColor: blue }} onClick={() => this.changeColumnColor(blue!)}></div>
+                    <div className={"columnMenu-colorPicker" + (selected === yellow ? " active" : "")} style={{ backgroundColor: yellow }} onClick={() => this.changeColumnColor(yellow!)}></div>
+                    <div className={"columnMenu-colorPicker" + (selected === red ? " active" : "")} style={{ backgroundColor: red }} onClick={() => this.changeColumnColor(red!)}></div>
+                    <div className={"columnMenu-colorPicker" + (selected === gray ? " active" : "")} style={{ backgroundColor: gray }} onClick={() => this.changeColumnColor(gray)}></div>
                 </div>
             </div>
         );
@@ -193,8 +217,8 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
     renderContent = () => {
         return (
             <div className="collectionSchema-header-menuOptions">
-                <label>Key:</label>
                 <div className="collectionSchema-headerMenu-group">
+                    <label>Key:</label>
                     <KeysDropdown
                         keyValue={this.props.columnField.heading}
                         possibleKeys={this.props.possibleKeys}
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index ca2684ba2..746a09c11 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -277,16 +277,29 @@ button.add-column {
 
 .collectionSchema-header-menuOptions {
     color: black;
-    width: 175px;
+    width: 200px;
     text-align: left;
 
     .collectionSchema-headerMenu-group {
-        margin-bottom: 10px;
+        padding: 7px 0;
+        border-bottom: 1px solid lightgray;
+
+        &:first-child {
+            padding-top : 0;
+        }
+
+        &:last-child {
+            border: none;
+            text-align: center;
+            padding: 12px 0 0 0;
+        }
     }
 
     label {
         color: $main-accent;
         font-weight: normal;
+        letter-spacing: 2px;
+        text-transform: uppercase;
     }
 
     input {
@@ -294,9 +307,43 @@ button.add-column {
         width: 100%;
     }
 
+    .columnMenu-option {
+        cursor: pointer;
+        padding: 3px;
+        background-color: white;
+        transition: background-color 0.2s;
+
+        &:hover {
+            background-color: $light-color-secondary; 
+        }
+
+        &.active {
+            font-weight: bold;
+            border: 2px solid $light-color-secondary;
+        }
+
+        svg {
+            color: gray;
+            margin-right: 5px;
+            width: 10px;
+        }
+    }
+
     .keys-dropdown {
         position: relative;
-        max-width: 175px;
+        // max-width: 175px;
+        width: 100%;
+
+        input {
+            border: 2px solid $light-color-secondary;
+            padding: 3px;
+            height: 28px;
+            font-weight: bold;
+
+            &:focus {
+                font-weight: normal;
+            }
+        }
 
         .keys-options-wrapper {
             width: 100%;
@@ -321,43 +368,11 @@ button.add-column {
         }
     }
 
-    .columnMenu-types {
-        display: flex;
-        justify-content: space-between;
-
-        button {
-            border-radius: 20px;
-            width: 22px;
-            height: 22px;
-            text-align: center;
-            display: flex;
-            justify-content: center;
-            flex-direction: column;
-            padding: 0;
-
-            &.active {
-                border: 2px solid white;
-                box-shadow: 0 0 0 2px lightgray;
-            }
-        }
-    }
-
     .columnMenu-colors {
         display: flex;
         justify-content: space-between;
         flex-wrap: wrap;
 
-        // input[type="radio"] {
-        //     display: none;
-        // }
-
-        // input[type="radio"]:checked + label {
-        //     .columnMenu-colorPicker {
-        //         border: 2px solid white;
-        //         box-shadow: 0 0 0 2px  lightgray;
-        //     }
-        // }
-
         .columnMenu-colorPicker {
             cursor: pointer;
             width: 20px;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 722d8b1f9..86d3d01ef 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -612,7 +612,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             } else {
                 const index = columns.map(c => c.heading).indexOf(oldKey);
                 if (index > -1) {
-                    columns[index] = new SchemaHeaderField(newKey, columns[index].color);
+                    let column = columns[index];
+                    column.setHeading(newKey);
+                    columns[index] = column;
                     this.columns = columns;
                 }
             }
@@ -643,8 +645,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let columns = this.columns;
         let index = columns.indexOf(columnField);
         if (index > -1) {
-            // let column = columns[index];
-            columnField.type = NumCast(type);
+            columnField.setType(NumCast(type));
             columns[index] = columnField;
             this.columns = columns;
         }
@@ -664,9 +665,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         let columns = this.columns;
         let index = columns.indexOf(columnField);
         if (index > -1) {
-            columnField.color = color;
+            columnField.setColor(color);
             columns[index] = columnField;
-            this.columns = columns;
+            this.columns = columns; // need to set the columns to trigger rerender
         }
     }
 
diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts
index 15b497759..bccf82a9e 100644
--- a/src/new_fields/SchemaHeaderField.ts
+++ b/src/new_fields/SchemaHeaderField.ts
@@ -15,7 +15,7 @@ export const PastelSchemaPalette = new Map<string, string>([
     ["purple2", "#c5a3ff"],
     ["purple3", "#d5aaff"],
     ["purple4", "#ecd4ff"],
-    ["purple5", "#fb34ff"],
+    // ["purple5", "#fb34ff"],
     ["purple6", "#dcd3ff"],
     ["purple7", "#a79aff"],
     ["purple8", "#b5b9ff"],
-- 
cgit v1.2.3-70-g09d2


From 78999b8b35267db9236bbb69e7e90e8691c59ba9 Mon Sep 17 00:00:00 2001
From: fawn <fangrui_tong@brown.edu>
Date: Tue, 30 Jul 2019 16:21:54 -0400
Subject: sorting saves on schema columns

---
 .../views/collections/CollectionSchemaHeaders.tsx  | 18 ++++++------
 .../views/collections/CollectionSchemaView.tsx     | 33 +++++++++++++---------
 src/new_fields/SchemaHeaderField.ts                | 22 ++++++++++-----
 3 files changed, 45 insertions(+), 28 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index 62762962e..4f0681f6c 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -24,8 +24,7 @@ export interface HeaderProps {
     setIsEditing: (isEditing: boolean) => void;
     deleteColumn: (column: string) => void;
     setColumnType: (column: SchemaHeaderField, type: ColumnType) => void;
-    setColumnSort: (key: string, desc: boolean) => void;
-    removeColumnSort: (key: string) => void;
+    setColumnSort: (column: SchemaHeaderField, desc: boolean | undefined) => void;
     setColumnColor: (column: SchemaHeaderField, color: string) => void;
 
 }
@@ -51,7 +50,6 @@ export class CollectionSchemaHeader extends React.Component<HeaderProps> {
                     onlyShowOptions={false}
                     setColumnType={this.props.setColumnType}
                     setColumnSort={this.props.setColumnSort}
-                    removeColumnSort={this.props.removeColumnSort}
                     setColumnColor={this.props.setColumnColor}
                 />
             </div>
@@ -87,8 +85,7 @@ export interface ColumnMenuProps {
     deleteColumn: (column: string) => void;
     onlyShowOptions: boolean;
     setColumnType: (column: SchemaHeaderField, type: ColumnType) => void;
-    setColumnSort: (key: string, desc: boolean) => void;
-    removeColumnSort: (key: string) => void;
+    setColumnSort: (column: SchemaHeaderField, desc: boolean | undefined) => void;
     anchorPoint?: any;
     setColumnColor: (column: SchemaHeaderField, color: string) => void;
 }
@@ -123,6 +120,10 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
         this.props.setColumnType(this.props.columnField, type);
     }
 
+    changeColumnSort = (desc: boolean | undefined): void => {
+        this.props.setColumnSort(this.props.columnField, desc);
+    }
+
     changeColumnColor = (color: string): void => {
         this.props.setColumnColor(this.props.columnField, color);
     }
@@ -168,19 +169,20 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps>
     }
 
     renderSorting = () => {
+        let sort = this.props.columnField.desc;
         return (
             <div className="collectionSchema-headerMenu-group">
                 <label>Sort by:</label>
                 <div className="columnMenu-sort">
-                    <div className="columnMenu-option" onClick={() => this.props.setColumnSort(this.props.columnField.heading, true)}>
+                    <div className={"columnMenu-option" + (sort === true ? " active" : "")} onClick={() => this.changeColumnSort(true)}>
                         <FontAwesomeIcon icon="sort-amount-down" size="sm" />
                         Sort descending
                     </div>
-                    <div className="columnMenu-option" onClick={() => this.props.setColumnSort(this.props.columnField.heading, false)}>
+                    <div className={"columnMenu-option" + (sort === false ? " active" : "")} onClick={() => this.changeColumnSort(false)}>
                         <FontAwesomeIcon icon="sort-amount-up" size="sm" />
                         Sort ascending
                     </div>
-                    <div className="columnMenu-option" onClick={() => this.props.removeColumnSort(this.props.columnField.heading)}>
+                    <div className="columnMenu-option" onClick={() => this.changeColumnSort(undefined)}>
                         <FontAwesomeIcon icon="times" size="sm" />
                         Clear sorting
                     </div>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 86d3d01ef..84f8ec505 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -275,7 +275,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @observable _headerIsEditing: boolean = false;
     @observable _cellIsEditing: boolean = false;
     @observable _focusedCell: { row: number, col: number } = { row: 0, col: 0 };
-    @observable _sortedColumns: Map<string, { id: string, desc: boolean }> = new Map();
     @observable _openCollections: Array<string> = [];
 
     @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); }
@@ -308,8 +307,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     @computed get resized(): { "id": string, "value": number }[] {
-        let columns = this.columns;
-        return columns.reduce((resized, shf) => {
+        return this.columns.reduce((resized, shf) => {
             if (shf.width > -1) {
                 resized.push({ "id": shf.heading, "value": shf.width });
             }
@@ -317,6 +315,15 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         }, [] as { "id": string, "value": number }[]);
     }
 
+    @computed get sorted(): { "id": string, "desc": boolean }[] {
+        return this.columns.reduce((sorted, shf) => {
+            if (shf.desc) {
+                sorted.push({ "id": shf.heading, "desc": shf.desc });
+            }
+            return sorted;
+        }, [] as { "id": string, "desc": boolean }[]);
+    }
+
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
     @computed get tableColumns(): Column<Doc>[] {
         let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.heading.toUpperCase() === key.toUpperCase()) === -1);
@@ -358,7 +365,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                 deleteColumn={this.deleteColumn}
                 setColumnType={this.setColumnType}
                 setColumnSort={this.setColumnSort}
-                removeColumnSort={this.removeColumnSort}
                 setColumnColor={this.setColumnColor}
             />;
 
@@ -689,13 +695,13 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     }
 
     @action
-    setColumnSort = (column: string, descending: boolean) => {
-        this._sortedColumns.set(column, { id: column, desc: descending });
-    }
-
-    @action
-    removeColumnSort = (column: string) => {
-        this._sortedColumns.delete(column);
+    setColumnSort = (columnField: SchemaHeaderField, descending: boolean | undefined) => {
+        let columns = this.columns;
+        let index = columns.findIndex(c => c.heading === columnField.heading);
+        let column = columns[index];
+        column.setDesc(descending);
+        columns[index] = column;
+        this.columns = columns;
     }
 
     get documentKeys() {
@@ -750,7 +756,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             getTdProps={this.getTdProps}
             sortable={false}
             TrComponent={MovableRow}
-            sorted={Array.from(this._sortedColumns.values())}
+            sorted={this.sorted}
             expanded={expanded}
             resized={this.resized}
             onResizedChange={this.onResizedChange}
@@ -770,7 +776,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         newResized.forEach(resized => {
             let index = columns.findIndex(c => c.heading === resized.id);
             let column = columns[index];
-            column.width = resized.value;
+            column.setWidth(resized.value);
+            columns[index] = column;
         });
         this.columns = columns;
     }
diff --git a/src/new_fields/SchemaHeaderField.ts b/src/new_fields/SchemaHeaderField.ts
index bccf82a9e..0c19d211a 100644
--- a/src/new_fields/SchemaHeaderField.ts
+++ b/src/new_fields/SchemaHeaderField.ts
@@ -51,19 +51,17 @@ export class SchemaHeaderField extends ObjectField {
     type: number;
     @serializable(primitive())
     width: number;
+    @serializable(primitive())
+    desc: boolean | undefined; // boolean determines sort order, undefined when no sort
 
-    constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType, width?: number) {
+    constructor(heading: string = "", color: string = RandomPastel(), type?: ColumnType, width?: number, desc?: boolean) {
         super();
 
         this.heading = heading;
         this.color = color;
-        if (type) {
-            this.type = type;
-        }
-        else {
-            this.type = 0;
-        }
+        this.type = type ? type : 0;
         this.width = width ? width : -1;
+        this.desc = desc;
     }
 
     setHeading(heading: string) {
@@ -81,6 +79,16 @@ export class SchemaHeaderField extends ObjectField {
         this[OnUpdate]();
     }
 
+    setWidth(width: number) {
+        this.width = width;
+        this[OnUpdate]();
+    }
+
+    setDesc(desc: boolean | undefined) {
+        this.desc = desc;
+        this[OnUpdate]();
+    }
+
     [Copy]() {
         return new SchemaHeaderField(this.heading, this.color, this.type);
     }
-- 
cgit v1.2.3-70-g09d2


From f73d1eabb7ce1fb49b35c8b2ce7be585d93b22ea Mon Sep 17 00:00:00 2001
From: fawn <fangrui_tong@brown.edu>
Date: Tue, 30 Jul 2019 18:43:19 -0400
Subject: minor schema styling

---
 .../views/collections/CollectionSchemaCells.tsx    | 20 ++++++----
 .../CollectionSchemaMovableTableHOC.tsx            |  1 -
 .../views/collections/CollectionSchemaView.scss    | 44 ++++++++++------------
 .../views/collections/CollectionSchemaView.tsx     |  3 ++
 4 files changed, 34 insertions(+), 34 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 4b3dd3cc1..61f21006e 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -71,6 +71,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
             document.removeEventListener("keydown", this.onKeyDown);
             this._isEditing = true;
             this.props.setIsEditing(true);
+
         }
     }
 
@@ -87,6 +88,9 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
         this.props.setPreviewDoc(this.props.rowProps.original);
 
+        // this._isEditing = true;
+        // this.props.setIsEditing(true);
+
         let field = this.props.rowProps.original[this.props.rowProps.column.id!];
         let doc = FieldValue(Cast(field, Doc));
         if (typeof field === "object" && doc) this.props.setPreviewDoc(doc);
@@ -122,17 +126,17 @@ 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));
+    // 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!);
+    //     console.log("Expanding doc", StrCast(doc!.title));
+    //     this.props.setPreviewDoc(doc!);
 
-        // this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
+    //     // this.props.changeFocusedCellByIndex(this.props.row, this.props.col);
 
-        e.stopPropagation();
-    }
+    //     e.stopPropagation();
+    // }
 
     renderCellWithType(type: string | undefined) {
         let dragRef: React.RefObject<HTMLDivElement> = React.createRef();
diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index 483463c2b..5741c4191 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -225,7 +225,6 @@ export class MovableRow extends React.Component<MovableRowProps> {
         let className = "collectionSchema-row";
         if (this.props.rowFocused) className += " row-focused";
         if (this.props.rowWrapped) className += " row-wrapped";
-        // if (!this.props.rowWrapped) className += " row-unwrapped";
 
         return (
             <div className={className} ref={this.createRowDropTarget} onContextMenu={this.onRowContextMenu}>
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 564e4f4a5..2946fc4f7 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -120,6 +120,7 @@
             padding: 0;
             border: solid lightgray;
             border-width: 0 1px;
+            border-bottom: 2px solid lightgray;
         }
     }
 
@@ -127,7 +128,7 @@
         // max-height: $MAX_ROW_HEIGHT;
         font-size: 13px;
         text-align: center;
-        background-color: $light-color-secondary;
+        // background-color: $light-color-secondary;
 
         &:last-child {
             overflow: visible;
@@ -145,25 +146,11 @@
         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
-
-        // &:nth-child(even) {
-        //     background-color: $light-color;
-        // }
-
-        // &:nth-child(odd) {
-        //     background-color: $light-color-secondary;
-        // }
 
         // &:first-child {
-        //     border-top: 1px solid $light-color-secondary !important;
-        // }
-        // &:last-child {
-        //     border-bottom: 1px solid $light-color-secondary !important;
+        //     .rt-td {
+        //         border-top: 1px solid lightgray !important;
+        //     }
         // }
     }
 
@@ -215,7 +202,6 @@
 
     .rt-resizable-header:last-child {
         overflow: visible;
-        border: 3px solid red !important;
 
         .rt-resizer {
             width: 5px !important;
@@ -396,8 +382,9 @@ button.add-column {
     background-color: white;
     // white-space: nowrap;
 
-    &.row-focused .rt-tr {
+    &.row-focused .rt-td {
         background-color: rgb(255, 246, 246); //$light-color-secondary;
+        // background-color: $light-color;
     }
 
     &.row-wrapped {
@@ -473,15 +460,22 @@ button.add-column {
         outline: none;
     }
 
-    &.focused {
-        // background-color: yellowgreen;
-        // border: 2px solid yellowgreen;
-
+    &.editing {
+        padding: 0;
         input {
             outline: 0;
             border: none;
-            background-color: yellow;
+            background-color: rgb(255, 217, 217);
+            width: 100%;
+            height: 100%;
+            padding: 2px 3px;
+            min-height: 26px;
         }
+    }
+
+    &.focused {
+        // background-color: yellowgreen;
+        // border: 2px solid yellowgreen;
 
         &.inactive {
             // border: 2px solid rgba(255, 255, 0, 0.4);
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 508d1f99d..a666a428b 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -477,6 +477,8 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         //@ts-ignore
         let col = this.columns.map(c => c.heading).indexOf(column!.id);
         let isFocused = this._focusedCell.row === row && this._focusedCell.col === col && this.props.isFocused(this.props.Document);
+        let isEditing = this.props.isFocused(this.props.Document) && this._cellIsEditing;
+        // TODO: editing border doesn't work :(
         return {
             style: {
                 border: !this._headerIsEditing && isFocused ? "2px solid rgb(255, 160, 160)" : "1px solid #f1efeb"
@@ -497,6 +499,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @action
     setCellIsEditing = (isEditing: boolean): void => {
+        console.log("SET CELL IS EDITING", isEditing);
         this._cellIsEditing = isEditing;
     }
 
-- 
cgit v1.2.3-70-g09d2


From b1848431fe96e2653590864cbf2127e1904df47b Mon Sep 17 00:00:00 2001
From: fawn <fangrui_tong@brown.edu>
Date: Tue, 30 Jul 2019 18:54:25 -0400
Subject: code cleaning

---
 .../views/collections/CollectionSchemaView.scss    | 82 ++--------------------
 .../views/collections/CollectionSchemaView.tsx     | 16 -----
 2 files changed, 4 insertions(+), 94 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 2946fc4f7..3c4279eea 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -9,27 +9,12 @@
     position: absolute;
     top: 0;
     width: 100%;
-    // transition: height .5s;
-    // transition: margin-top .5s;
     height: 100%;
-    // overflow: hidden;
-    // overflow-x: scroll;
-    // border: none;
-    // overflow: scroll;
-    // overflow-y: scroll;
     transition: top 0.5s;
     display: flex;
     justify-content: space-between;
     flex-wrap: nowrap;
 
-    // .collectionSchemaView-cellContents {
-    //     height: $MAX_ROW_HEIGHT;
-
-    //     img {
-    //         width: auto;
-    //         max-height: $MAX_ROW_HEIGHT;
-    //     }
-    // }
 
     .collectionSchemaView-tableContainer {
         width: 100%;
@@ -40,7 +25,6 @@
     .collectionSchemaView-previewRegion {
         position: relative;
         background: $light-color;
-        // float: left;
         height: 100%;
 
         .collectionSchemaView-previewDoc {
@@ -64,7 +48,6 @@
 
     .collectionSchemaView-dividerDragger {
         position: relative;
-        // float: left;
         height: 100%;
         width: 20px;
         z-index: 20;
@@ -72,24 +55,17 @@
         top: 0;
         background: gray;
         cursor: col-resize;
-        // background: $main-accent;
-        // box-sizing: border-box;
-        // border-left: 1px solid $intermediate-color;
-        // border-right: 1px solid $intermediate-color;
     }
 }
 
 .ReactTable {
     width: 100%;
-    // height: 100%;
     background: white;
     box-sizing: border-box;
     border: none !important;
     float: none !important;
 
     .rt-table {
-        // overflow-y: auto;
-        // overflow-x: auto;
         height: 100%;
         display: -webkit-inline-box;
         direction: ltr; 
@@ -101,14 +77,9 @@
         margin-left: 50px;
 
         &.-header {
-            // background: $intermediate-color;
-            // color: $light-color;
             font-size: 12px;
             height: 30px;
-            // border: 1px solid $intermediate-color;
             box-shadow: none;
-            // width: calc(100% - 30px);
-            // margin-right: -30px;
         }
 
         .rt-resizable-header-content {
@@ -125,10 +96,8 @@
     }
 
     .rt-th {
-        // max-height: $MAX_ROW_HEIGHT;
         font-size: 13px;
         text-align: center;
-        // background-color: $light-color-secondary;
 
         &:last-child {
             overflow: visible;
@@ -146,30 +115,17 @@
         flex: 0 1 auto;
         min-height: 30px;
         border: 0 !important;
-
-        // &:first-child {
-        //     .rt-td {
-        //         border-top: 1px solid lightgray !important;
-        //     }
-        // }
     }
 
     .rt-tr {
         width: 100%;
         min-height: 30px;
-        // height: $MAX_ROW_HEIGHT;
     }
 
     .rt-td {
-        // 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;
         text-align: center;
-        // white-space: normal;
         white-space: nowrap;
 
         .imageBox-cont {
@@ -252,11 +208,6 @@
                 margin-right: 4px;
             }
         }
-
-        // div[class*="css"] {
-        //     width: 100%;
-        //     height: 100%;
-        // }
     }
 }
 
@@ -320,7 +271,6 @@ button.add-column {
 
     .keys-dropdown {
         position: relative;
-        // max-width: 175px;
         width: 100%;
 
         input {
@@ -339,14 +289,15 @@ button.add-column {
             max-height: 150px;
             overflow-y: scroll;
             position: absolute;
-            top: 20px;
+            top: 28px;
+            box-shadow: 0 10px 16px rgba(0,0,0,0.1);
 
             .key-option {
                 background-color: $light-color;
-                border: 1px solid $light-color-secondary;
+                border: 1px solid lightgray;
                 padding: 2px 3px;
 
-                &:not(:last-child) {
+                &:not(:first-child) {
                     border-top: 0;
                 }
 
@@ -377,14 +328,11 @@ button.add-column {
 }
 
 .collectionSchema-row {
-    // height: $MAX_ROW_HEIGHT;
     height: 100%;
     background-color: white;
-    // white-space: nowrap;
 
     &.row-focused .rt-td {
         background-color: rgb(255, 246, 246); //$light-color-secondary;
-        // background-color: $light-color;
     }
 
     &.row-wrapped {
@@ -396,21 +344,15 @@ button.add-column {
     .row-dragger {
         display: flex;
         justify-content: space-around;
-        // height: $MAX_ROW_HEIGHT;
         flex: 50 0 auto;
         width: 50px;
         max-width: 50px;
         height: 100%;
         min-height: 30px;
-        // padding: 5px 5px 5px 0;
         color: lightgray;
         background-color: white;
         transition: color 0.1s ease;
 
-        // &:hover {
-        //     color: lightgray;
-        // }
-
         .row-option {
             // padding: 5px;
             cursor: pointer;
@@ -426,7 +368,6 @@ button.add-column {
     }
 
     .collectionSchema-row-wrapper {
-        // max-height: $MAX_ROW_HEIGHT;
 
         &.row-above {
             border-top: 1px solid red;
@@ -474,11 +415,8 @@ button.add-column {
     }
 
     &.focused {
-        // background-color: yellowgreen;
-        // border: 2px solid yellowgreen;
 
         &.inactive {
-            // border: 2px solid rgba(255, 255, 0, 0.4);
             border: none;
         }
     }
@@ -486,7 +424,6 @@ button.add-column {
     p {
         width: 100%;
         height: 100%;
-        // word-wrap: break-word;
     }
 
     &:hover .collectionSchemaView-cellContents-docExpander {
@@ -513,9 +450,7 @@ button.add-column {
     display: flex;
     justify-content: flex-end;
     padding: 0 10px;
-
     border-bottom: 2px solid gray;
-    // margin-bottom: 10px;
 
     .collectionSchemaView-toolbar-item {
         display: flex;
@@ -530,26 +465,17 @@ button.add-column {
 }
 
 .collectionSchemaView-table {
-    // width: calc(100% - 7px);
     width: 100%;
     height: 100%;
-    // overflow-y: scroll;
     overflow: visible;
 }
 
 .sub {
     padding: 10px 30px;
-    // padding-left: 80px;
     background-color: rgb(252, 252, 252);
     width: calc(100% - 50px);
     margin-left: 50px;
 
-    // .rt-table {
-    //     // overflow-x: hidden; // todo; this shouldnt be like this :((
-    //     // overflow-y: visible;
-    //     // overflow: visible;
-    // } // TODO fix
-
     .row-dragger {
         background-color: rgb(252, 252, 252);
     }
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index a666a428b..0a77008ec 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -44,7 +44,6 @@ export enum ColumnType {
     String,
     Boolean,
     Doc,
-    // Checkbox
 }
 // this map should be used for keys that should have a const type of value
 const columnTypes: Map<string, ColumnType> = new Map([
@@ -75,14 +74,6 @@ 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);
-    //     }
-    // }
-
     isFocused = (doc: Doc): boolean => {
         if (!this.props.isSelected()) return false;
         return doc === this._focusedTable;
@@ -119,8 +110,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
         let movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0];
         let width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth;
         this.props.Document.schemaPreviewWidth = width;
-        // 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 => {
@@ -257,7 +246,6 @@ export interface SchemaTableProps {
     deleteDocument: (document: Doc) => boolean;
     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;
@@ -269,7 +257,6 @@ export interface SchemaTableProps {
 
 @observer
 export class SchemaTable extends React.Component<SchemaTableProps> {
-    // private _mainCont?: HTMLDivElement;
     private DIVIDER_WIDTH = 4;
 
     @observable _headerIsEditing: boolean = false;
@@ -499,7 +486,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
 
     @action
     setCellIsEditing = (isEditing: boolean): void => {
-        console.log("SET CELL IS EDITING", isEditing);
         this._cellIsEditing = isEditing;
     }
 
@@ -739,8 +725,6 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
     @computed
     get reactTable() {
         let children = this.childDocs;
-
-        // let previewWidth = this.previewWidth(); // + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1;
         let hasCollectionChild = children.reduce((found, doc) => found || doc.type === "collection", false);
         let expandedRowsList = this._openCollections.map(col => children.findIndex(doc => doc[Id] === col).toString());
         let expanded = {};
-- 
cgit v1.2.3-70-g09d2


From d267b4fae181d52d3862fe5a2b1a719fdaa180a5 Mon Sep 17 00:00:00 2001
From: yipstanley <stanley_yip@brown.edu>
Date: Tue, 30 Jul 2019 19:36:39 -0400
Subject: schema fix

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

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 0a77008ec..26b9de3e7 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -222,7 +222,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     render() {
         Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey);
         return (
-            <div className="collectionSchemaView-container" style={{ height: this.props.chromeCollapsed ? "100%" : "calc(100% - 70px", marginTop: this.props.chromeCollapsed ? "0" : "70px", transition: "all .5s" }}>
+            <div className="collectionSchemaView-container" style={{ height: "100%", marginTop: "0", }}>
                 <div className="collectionSchemaView-tableContainer" onPointerDown={this.onPointerDown} onWheel={this.onWheel} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createTarget}>
                     {this.schemaTable}
                 </div>
-- 
cgit v1.2.3-70-g09d2


From a28a3b79f81e82e4b3368c0e87d3a56c694cc3b4 Mon Sep 17 00:00:00 2001
From: Sam Wilkins <abdullah_ahmed@brown.edu>
Date: Tue, 30 Jul 2019 21:24:45 -0400
Subject: added undo to schema

---
 src/client/views/collections/CollectionSchemaCells.tsx         |  2 ++
 src/client/views/collections/CollectionSchemaHeaders.tsx       |  2 ++
 .../views/collections/CollectionSchemaMovableTableHOC.tsx      |  2 ++
 src/client/views/collections/CollectionSchemaView.tsx          | 10 ++++++++++
 src/client/views/collections/CollectionViewChromes.tsx         |  2 ++
 5 files changed, 18 insertions(+)

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

diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 61f21006e..4ff65b277 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -26,6 +26,7 @@ import { faExpand } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
 import { KeyCodes } from "../../northstar/utils/KeyCodes";
+import { undoBatch } from "../../util/UndoManager";
 
 library.add(faExpand);
 
@@ -96,6 +97,7 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         if (typeof field === "object" && doc) this.props.setPreviewDoc(doc);
     }
 
+    @undoBatch
     applyToDoc = (doc: Doc, row: number, col: number, run: (args?: { [name: string]: any }) => any) => {
         const res = run({ this: doc, $r: row, $c: col, $: (r: number = 0, c: number = 0) => this.props.getField(r + row, c + col) });
         if (!res.success) return false;
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index 4f0681f6c..dfd65770e 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -11,6 +11,7 @@ import { emptyFunction } from "../../../Utils";
 import { contains } from "typescript-collections/dist/lib/arrays";
 import { faFile } from "@fortawesome/free-regular-svg-icons";
 import { SchemaHeaderField, RandomPastel, PastelSchemaPalette } from "../../../new_fields/SchemaHeaderField";
+import { undoBatch } from "../../util/UndoManager";
 
 library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faFile, faSortAmountDown, faSortAmountUp, faTimes);
 
@@ -286,6 +287,7 @@ class KeysDropdown extends React.Component<KeysDropdownProps> {
         this.props.setIsEditing(false);
     }
 
+    @undoBatch
     @action
     onKeyDown = (e: React.KeyboardEvent): void => {
         if (e.key === "Enter") {
diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
index 5741c4191..ec40043cc 100644
--- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
+++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx
@@ -13,6 +13,7 @@ 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";
+import { undoBatch } from "../../util/UndoManager";
 
 library.add(faGripVertical, faTrash);
 
@@ -196,6 +197,7 @@ export class MovableRow extends React.Component<MovableRowProps> {
         ContextMenu.Instance.addItem({ description: description, event: () => this.props.textWrapRow(this.props.rowInfo.original), icon: "file-pdf" });
     }
 
+    @undoBatch
     @action
     move: DragManager.MoveFunction = (doc: Doc, target: Doc, addDoc) => {
         let targetView = DocumentManager.Instance.getDocumentView(target);
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 26b9de3e7..4d6bf437f 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -176,6 +176,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
             />
         </div>;
     }
+
+    @undoBatch
     @action
     setPreviewScript = (script: string) => {
         this.previewScript = script;
@@ -552,6 +554,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         this.props.setFocused(this.props.Document);
     }
 
+    @undoBatch
     createRow = () => {
         let children = this.childDocs;
 
@@ -563,6 +566,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         this.childDocs = children;
     }
 
+    @undoBatch
     @action
     createColumn = () => {
         let index = 0;
@@ -581,6 +585,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         this.columns = columns;
     }
 
+    @undoBatch
     @action
     deleteColumn = (key: string) => {
         let columns = this.columns;
@@ -595,6 +600,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         }
     }
 
+    @undoBatch
     @action
     changeColumns = (oldKey: string, newKey: string, addNew: boolean) => {
         let columns = this.columns;
@@ -634,6 +640,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         return NumCast(typesDoc[column.heading]);
     }
 
+    @undoBatch
     setColumnType = (columnField: SchemaHeaderField, type: ColumnType): void => {
         if (columnTypes.get(columnField.heading)) return;
 
@@ -656,6 +663,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         // }
     }
 
+    @undoBatch
     setColumnColor = (columnField: SchemaHeaderField, color: string): void => {
         let columns = this.columns;
         let index = columns.indexOf(columnField);
@@ -671,6 +679,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         this.columns = columns;
     }
 
+    @undoBatch
     reorderColumns = (toMove: SchemaHeaderField, relativeTo: SchemaHeaderField, before: boolean, columnsValues: SchemaHeaderField[]) => {
         let columns = [...columnsValues];
         let oldIndex = columns.indexOf(toMove);
@@ -683,6 +692,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
         this.columns = columns;
     }
 
+    @undoBatch
     @action
     setColumnSort = (columnField: SchemaHeaderField, descending: boolean | undefined) => {
         let columns = this.columns;
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index bf1f35a92..ecf78b8c1 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -377,6 +377,7 @@ export class CollectionStackingViewChrome extends React.Component<CollectionView
 export class CollectionSchemaViewChrome extends React.Component<CollectionViewChromeProps> {
     // private _textwrapAllRows: boolean = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
 
+    @undoBatch
     togglePreview = () => {
         let dividerWidth = 4;
         let borderWidth = Number(COLLECTION_BORDER_WIDTH);
@@ -386,6 +387,7 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionViewCh
         this.props.CollectionView.props.Document.schemaPreviewWidth = previewWidth === 0 ? Math.min(tableWidth / 3, 200) : 0;
     }
 
+    @undoBatch
     @action
     toggleTextwrap = async () => {
         let textwrappedRows = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []);
-- 
cgit v1.2.3-70-g09d2


From a75f6fb17a4cbb4643cff0d347eb812138957c95 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 31 Jul 2019 11:48:29 -0400
Subject: fixed some css and creating text links.

---
 src/client/views/collections/CollectionSchemaView.scss | 8 ++++----
 src/client/views/collections/CollectionSchemaView.tsx  | 1 +
 src/client/views/collections/CollectionView.tsx        | 3 +++
 src/new_fields/Doc.ts                                  | 8 ++++++--
 4 files changed, 14 insertions(+), 6 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 3c4279eea..01744fb34 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -56,6 +56,10 @@
         background: gray;
         cursor: col-resize;
     }
+
+    .documentView-node:first-child {
+        background: $light-color;
+    }
 }
 
 .ReactTable {
@@ -171,10 +175,6 @@
     display: inline-block;
 }
 
-.documentView-node:first-child {
-    background: $light-color;
-}
-
 .collectionSchema-col {
     height: 100%;
 
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 4d6bf437f..9efd0d3ec 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -980,6 +980,7 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
                     style={{
                         transform: `translate(${this.centeringOffset}px, 0px)`,
                         borderRadius: this.borderRounding,
+                        display: "inline",
                         height: "100%"
                     }}>
                     <DocumentView
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 34adc5840..57dc5879b 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -111,6 +111,9 @@ export class CollectionView extends React.Component<FieldViewProps> {
             }
             ContextMenu.Instance.addItem({ description: "View Modes...", subitems: subItems, icon: "eye" });
             ContextMenu.Instance.addItem({ description: "Apply Template", event: () => this.props.addDocTab && this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" });
+            ContextMenu.Instance.addItem({
+                description: this.props.Document.chromeStatus !== "disabled" ? "Hide Chrome" : "Show Chrome", event: () => this.props.Document.chromeStatus = (this.props.Document.chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram"
+            });
         }
     }
 
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 5f9df786e..84b8589dd 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -197,8 +197,12 @@ export namespace Doc {
     }
 
     export function Get(doc: Doc, key: string, ignoreProto: boolean = false): FieldResult {
-        const self = doc[Self];
-        return getField(self, key, ignoreProto);
+        try {
+            const self = doc[Self];
+            return getField(self, key, ignoreProto);
+        } catch  {
+            return doc;
+        }
     }
     export function GetT<T extends Field>(doc: Doc, key: string, ctor: ToConstructor<T>, ignoreProto: boolean = false): FieldResult<T> {
         return Cast(Get(doc, key, ignoreProto), ctor) as FieldResult<T>;
-- 
cgit v1.2.3-70-g09d2


From 753615c80d4cf08605ebaaeeaf0a44a0fd88d898 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 3 Aug 2019 15:21:10 -0400
Subject: working version of clustering

---
 src/Utils.ts                                       |   2 +
 src/client/documents/Documents.ts                  |   3 +-
 src/client/util/DragManager.ts                     |   8 +-
 src/client/views/MainView.tsx                      |   4 +-
 src/client/views/TemplateMenu.tsx                  |   5 +-
 .../views/collections/CollectionDockingView.tsx    |   3 +-
 .../views/collections/CollectionSchemaView.tsx     |   3 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 142 +++++++++++++--------
 .../collections/collectionFreeForm/MarqueeView.tsx |   1 +
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  12 +-
 src/client/views/nodes/DocumentView.tsx            |  17 +--
 .../views/presentationview/PresentationElement.tsx |   3 +-
 src/client/views/search/SearchItem.tsx             |   3 +-
 13 files changed, 125 insertions(+), 81 deletions(-)

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

diff --git a/src/Utils.ts b/src/Utils.ts
index 8df67df5d..502540eb0 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -140,6 +140,8 @@ export function returnOne() { return 1; }
 
 export function returnZero() { return 0; }
 
+export function returnEmptyString() { return ""; }
+
 export function emptyFunction() { }
 
 export type Without<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 09bafcf43..07e38a4c0 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -84,6 +84,7 @@ export interface DocumentOptions {
     templates?: List<string>;
     viewType?: number;
     backgroundColor?: string;
+    defaultBackgroundColor?: string;
     dropAction?: dropActionType;
     backgroundLayout?: string;
     chromeStatus?: string;
@@ -124,7 +125,7 @@ export namespace Docs {
         const TemplateMap: TemplateMap = new Map([
             [DocumentType.TEXT, {
                 layout: { view: FormattedTextBox },
-                options: { height: 150, backgroundColor: "#f1efeb" }
+                options: { height: 150, backgroundColor: "#f1efeb", defaultBackgroundColor: "#f1efeb" }
             }],
             [DocumentType.HIST, {
                 layout: { view: HistogramBox, collectionView: [CollectionView, data] as CollectionViewType },
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 0b5c785a4..a7aaaed7c 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -404,7 +404,8 @@ export namespace DragManager {
                 hideSource = options.hideSource();
             }
         }
-        eles.map(ele => (ele.hidden = hideSource));
+        eles.map(ele => (ele.hidden = hideSource) &&
+            (ele.parentElement && ele.parentElement.className.indexOf("collectionFreeFormDocumentView") !== -1 && (ele.parentElement.hidden = hideSource)));
 
         let lastX = downX;
         let lastY = downY;
@@ -434,7 +435,10 @@ export namespace DragManager {
 
         let hideDragElements = () => {
             dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement));
-            eles.map(ele => (ele.hidden = false));
+            eles.map(ele => {
+                ele.hidden = false;
+                (ele.parentElement && ele.parentElement.className.indexOf("collectionFreeFormDocumentView") !== -1 && (ele.parentElement.hidden = false));
+            });
         };
         let endDrag = () => {
             document.removeEventListener("pointermove", moveHandler, true);
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 2ecf5fd85..53f589684 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -15,7 +15,7 @@ import { listSpec } from '../../new_fields/Schema';
 import { Cast, FieldValue, NumCast, BoolCast, StrCast } from '../../new_fields/Types';
 import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
 import { RouteStore } from '../../server/RouteStore';
-import { emptyFunction, returnOne, returnTrue, Utils } from '../../Utils';
+import { emptyFunction, returnOne, returnTrue, Utils, returnEmptyString } from '../../Utils';
 import { DocServer } from '../DocServer';
 import { Docs } from '../documents/Documents';
 import { SetupDrag } from '../util/DragManager';
@@ -270,6 +270,7 @@ export class MainView extends React.Component {
                             PanelWidth={this.getPWidth}
                             PanelHeight={this.getPHeight}
                             renderDepth={0}
+                            backgroundColor={returnEmptyString}
                             selectOnLoad={false}
                             focus={emptyFunction}
                             parentActive={returnTrue}
@@ -334,6 +335,7 @@ export class MainView extends React.Component {
             renderDepth={0}
             selectOnLoad={false}
             focus={emptyFunction}
+            backgroundColor={returnEmptyString}
             parentActive={returnTrue}
             whenActiveChanged={emptyFunction}
             bringToFront={emptyFunction}
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index e654a0644..6dd908445 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -60,12 +60,9 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
                     let de = new DragManager.DocumentDragData([topDoc], [undefined]);
                     de.moveDocument = topDocView.props.moveDocument;
                     let xf = newDocView.ContentDiv!.getBoundingClientRect();
-                    console.log("ex = " + ex + " " + xf.left + " " + (ex - xf.left));
                     DragManager.StartDocumentDrag([newDocView.ContentDiv!], de, ex, ey, {
                         offsetX: (ex - xf.left), offsetY: (ey - xf.top),
-                        handlers: {
-                            dragComplete: () => { },
-                        },
+                        handlers: { dragComplete: () => { }, },
                         hideSource: false
                     });
                 }
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 588102f01..f559480ed 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -10,7 +10,7 @@ import { Id } from '../../../new_fields/FieldSymbols';
 import { FieldId } from "../../../new_fields/RefField";
 import { listSpec } from "../../../new_fields/Schema";
 import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types";
-import { emptyFunction, returnTrue, Utils, returnOne } from "../../../Utils";
+import { emptyFunction, returnTrue, Utils, returnOne, returnEmptyString } from "../../../Utils";
 import { DocServer } from "../../DocServer";
 import { DocumentManager } from '../../util/DocumentManager';
 import { DragLinksAsDocuments, DragManager } from "../../util/DragManager";
@@ -607,6 +607,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
             parentActive={returnTrue}
             whenActiveChanged={emptyFunction}
             focus={emptyFunction}
+            backgroundColor={returnEmptyString}
             addDocTab={this.addDocTab}
             ContainingCollectionView={undefined}
             zoomToScale={emptyFunction}
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 9efd0d3ec..8218877ba 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -6,7 +6,7 @@ import { action, computed, observable, trace, untracked } from "mobx";
 import { observer } from "mobx-react";
 import ReactTable, { CellInfo, ComponentPropsGetterR, Column, RowInfo, ResizedChangeFunction, Resize } from "react-table";
 import "react-table/react-table.css";
-import { emptyFunction, returnOne } from "../../../Utils";
+import { emptyFunction, returnOne, returnEmptyString } from "../../../Utils";
 import { Doc, DocListCast, Field, Opt } from "../../../new_fields/Doc";
 import { Id } from "../../../new_fields/FieldSymbols";
 import { List } from "../../../new_fields/List";
@@ -999,6 +999,7 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
                         PanelHeight={this.PanelHeight}
                         ContainingCollectionView={this.props.CollectionView}
                         focus={emptyFunction}
+                        backgroundColor={returnEmptyString}
                         parentActive={this.props.active}
                         whenActiveChanged={this.props.whenActiveChanged}
                         bringToFront={emptyFunction}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index bc1aee159..ee21c5a4d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,7 +1,7 @@
 import { library } from "@fortawesome/fontawesome-svg-core";
 import { faEye } from "@fortawesome/free-regular-svg-icons";
 import { faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faPaintBrush, faTable, faUpload } from "@fortawesome/free-solid-svg-icons";
-import { action, computed } from "mobx";
+import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, DocListCastAsync, HeightSym, WidthSym } from "../../../../new_fields/Doc";
 import { Id } from "../../../../new_fields/FieldSymbols";
@@ -9,7 +9,7 @@ import { InkField, StrokeData } from "../../../../new_fields/InkField";
 import { createSchema, makeInterface } from "../../../../new_fields/Schema";
 import { ScriptField } from "../../../../new_fields/ScriptField";
 import { BoolCast, Cast, FieldValue, NumCast, StrCast } from "../../../../new_fields/Types";
-import { emptyFunction, returnOne, Utils } from "../../../../Utils";
+import { emptyFunction, returnOne, Utils, returnFalse, returnEmptyString } from "../../../../Utils";
 import { CognitiveServices } from "../../../cognitive_services/CognitiveServices";
 import { DocServer } from "../../../DocServer";
 import { DocumentManager } from "../../../util/DocumentManager";
@@ -37,6 +37,8 @@ import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
 import v5 = require("uuid/v5");
+import { setScheduler } from "bluebird";
+import { DocumentType, Docs } from "../../../documents/Documents";
 
 library.add(faEye, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload);
 
@@ -132,17 +134,17 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         r2: { left: number, top: number, width: number, height: number }) {
         return !(r2.left > r1.left + r1.width || r2.left + r2.width < r1.left || r2.top > r1.top + r1.height || r2.top + r2.height < r1.top);
     }
-    _groupingBorder = 100;
+    _clusterDistance = 75;
     bounsdSelect(doc: Doc, doc2: Doc) {
-        var x2 = NumCast(doc2.x) - this._groupingBorder;
-        var y2 = NumCast(doc2.y) - this._groupingBorder;
-        var w2 = NumCast(doc2.width) + this._groupingBorder;
-        var h2 = NumCast(doc2.height) + this._groupingBorder;
-        var x = NumCast(doc.x) - this._groupingBorder;
-        var y = NumCast(doc.y) - this._groupingBorder;
-        var w = NumCast(doc.width) + this._groupingBorder;
-        var h = NumCast(doc.height) + this._groupingBorder;
-        if (this.intersectRect({ left: x, top: y, width: w, height: h }, { left: x2, top: y2, width: w2, height: h2 })) {
+        var x2 = NumCast(doc2.x) - this._clusterDistance;
+        var y2 = NumCast(doc2.y) - this._clusterDistance;
+        var w2 = NumCast(doc2.width) + this._clusterDistance;
+        var h2 = NumCast(doc2.height) + this._clusterDistance;
+        var x = NumCast(doc.x) - this._clusterDistance;
+        var y = NumCast(doc.y) - this._clusterDistance;
+        var w = NumCast(doc.width) + this._clusterDistance;
+        var h = NumCast(doc.height) + this._clusterDistance;
+        if (doc.z === doc2.z && this.intersectRect({ left: x, top: y, width: w, height: h }, { left: x2, top: y2, width: w2, height: h2 })) {
             return true;
         }
         return false;
@@ -197,36 +199,83 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         return false;
     }
 
+    tryDragCluster(e: PointerEvent) {
+        let probe = this.getTransform().transformPoint(e.clientX, e.clientY);
+        let cluster = this.childDocs.reduce((cluster, cd) => {
+            let cx = NumCast(cd.x) - this._clusterDistance;
+            let cy = NumCast(cd.y) - this._clusterDistance;
+            let cw = NumCast(cd.width) + 2 * this._clusterDistance;
+            let ch = NumCast(cd.height) + 2 * this._clusterDistance;
+            if (!cd.z && this.intersectRect({ left: cx, top: cy, width: cw, height: ch }, { left: probe[0], top: probe[1], width: 1, height: 1 }))
+                return NumCast(cd.cluster);
+            return cluster;
+        }, -1);
+        if (cluster !== -1) {
+            let eles = this.childDocs.filter(cd => NumCast(cd.cluster) === cluster);
+            this.selectDocuments(eles);
+            let clusterDocs = SelectionManager.SelectedDocuments();
+            SelectionManager.DeselectAll();
+            let de = new DragManager.DocumentDragData(eles, eles.map(d => undefined));
+            de.moveDocument = this.props.moveDocument;
+            const [left, top] = clusterDocs[0].props.ScreenToLocalTransform().scale(clusterDocs[0].props.ContentScaling()).inverse().transformPoint(0, 0);
+            const [xoff, yoff] = this.getTransform().transformDirection(e.x - left, e.y - top);
+            de.dropAction = e.ctrlKey || e.altKey ? "alias" : undefined;
+            de.xOffset = xoff;
+            de.yOffset = yoff;
+            DragManager.StartDocumentDrag(clusterDocs.map(v => v.ContentDiv!), de, e.clientX, e.clientY, {
+                handlers: { dragComplete: action(emptyFunction) },
+                hideSource: !de.dropAction
+            });
+            return true;
+        }
+
+        return false;
+    }
+    @observable sets: (Doc[])[] = [];
     @action
     updateClusters() {
-        let sets: (Doc[])[] = []
+        this.sets.length = 0;
         this.childDocs.map(c => {
             let included = []
-            for (let i = 0; i < sets.length; i++) {
-                for (let j = 0; j < sets[i].length; j++) {
-                    if (this.bounsdSelect(c, sets[i][j])) {
+            for (let i = 0; i < this.sets.length; i++) {
+                for (let j = 0; j < this.sets[i].length; j++) {
+                    if (this.bounsdSelect(c, this.sets[i][j])) {
                         included.push(i);
                         break;
                     }
                 }
             }
             if (included.length === 0)
-                sets.push([c]);
+                this.sets.push([c]);
             else if (included.length === 1)
-                sets[included[0]].push(c);
+                this.sets[included[0]].push(c);
             else {
-                sets[included[0]].push(c);
+                this.sets[included[0]].push(c);
                 for (let s = 1; s < included.length; s++) {
-                    sets[included[0]].push(...sets[included[s]]);
-                    sets[included[s]].length = 0;
+                    this.sets[included[0]].push(...this.sets[included[s]]);
+                    this.sets[included[s]].length = 0;
                 }
             }
         });
-        for (let s = 0; s < sets.length; s++) {
-            for (let i = 0; i < sets[s].length; i++) {
-                Doc.GetProto(sets[s][i]).cluster = s;
+        for (let s = 0; s < this.sets.length; s++) {
+            for (let i = 0; i < this.sets[s].length; i++) {
+                this.sets[s][i].cluster = s;
+            }
+        }
+    }
+
+    getClusterColor = (doc: Doc) => {
+        if (this.props.Document.useClusters) {
+            let cluster = NumCast(doc.cluster);
+            let set = this.sets.length > cluster ? this.sets[NumCast(doc.cluster)] : undefined;
+            let colors = ["#da42429e", "#31ea318c", "#8c4000", "#4a7ae2c4", "#d809ff", "#ff7601", "#1dffff", "yellow", "#1b8231f2", "#000000ad"];
+            let clusterColor = colors[cluster % colors.length];
+            for (let i = 0; set && i < set.length; i++) {
+                if (set[i].backgroundColor && set[i].backgroundColor !== set[i].defaultBackgroundColor) clusterColor = StrCast(set[i].backgroundColor);
             }
+            return clusterColor;
         }
+        return "";
     }
 
     @action
@@ -249,34 +298,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     @action
     onPointerMove = (e: PointerEvent): void => {
         if (!e.cancelBubble) {
-            let probe = this.getTransform().transformPoint(e.clientX, e.clientY);
-            let cluster = this.childDocs.reduce((cluster, cd) => {
-                let cx = NumCast(cd.x) - this._groupingBorder;
-                let cy = NumCast(cd.y) - this._groupingBorder;
-                let cw = NumCast(cd.width) + 2 * this._groupingBorder;
-                let ch = NumCast(cd.height) + 2 * this._groupingBorder;
-                if (this.intersectRect({ left: cx, top: cy, width: cw, height: ch }, { left: probe[0], top: probe[1], width: 1, height: 1 }))
-                    return NumCast(cd.cluster);
-                return cluster;
-            }, -1);
-            if (cluster !== -1) {
-                let eles = this.childDocs.filter(cd => NumCast(cd.cluster) === cluster);
-                this.selectDocuments(eles);
-                let clusterDocs = SelectionManager.SelectedDocuments();
-                SelectionManager.DeselectAll();
-                let de = new DragManager.DocumentDragData(eles, eles.map(d => undefined));
-                de.moveDocument = this.props.moveDocument;
-                const [left, top] = clusterDocs[0].props.ScreenToLocalTransform().scale(clusterDocs[0].props.ContentScaling()).inverse().transformPoint(0, 0);
-                const [xoff, yoff] = this.getTransform().transformDirection(e.x - left, e.y - top);
-                de.dropAction = e.ctrlKey || e.altKey ? "alias" : undefined;
-                de.xOffset = xoff;
-                de.yOffset = yoff;
-                DragManager.StartDocumentDrag(clusterDocs.map(v => v.ContentDiv!), de, e.clientX, e.clientY, {
-                    handlers: {
-                        dragComplete: action(emptyFunction)
-                    },
-                    hideSource: !de.dropAction
-                });
+            if (this.props.Document.useClusters && this.tryDragCluster(e)) {
                 e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document'  however it does mark the event as cancelBubble=true which we test for in the move event handlers
                 e.preventDefault();
                 document.removeEventListener("pointermove", this.onPointerMove);
@@ -493,6 +515,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             ContentScaling: returnOne,
             ContainingCollectionView: this.props.CollectionView,
             focus: this.focusDocument,
+            backgroundColor: this.getClusterColor,
             parentActive: this.props.active,
             whenActiveChanged: this.props.whenActiveChanged,
             bringToFront: this.bringToFront,
@@ -516,6 +539,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             ContentScaling: returnOne,
             ContainingCollectionView: this.props.CollectionView,
             focus: this.focusDocument,
+            backgroundColor: returnEmptyString,
             parentActive: this.props.active,
             whenActiveChanged: this.props.whenActiveChanged,
             bringToFront: this.bringToFront,
@@ -625,6 +649,15 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             event: async () => this.props.Document.fitToBox = !this.fitToBox,
             icon: !this.fitToBox ? "expand-arrows-alt" : "compress-arrows-alt"
         });
+        layoutItems.push({
+            description: `${this.props.Document.useClusters ? "Uncluster" : "Use Clusters"}`,
+            event: async () => {
+                Docs.Prototypes.get(DocumentType.TEXT).defaultBackgroundColor = "#f1efeb";
+                Docs.Prototypes.get(DocumentType.COL).defaultBackgroundColor = "white";
+                this.props.Document.useClusters = !this.props.Document.useClusters;
+            },
+            icon: !this.props.Document.useClusters ? "expand-arrows-alt" : "compress-arrows-alt"
+        });
         layoutItems.push({
             description: "Arrange contents in grid",
             icon: "table",
@@ -700,10 +733,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         ...this.views
     ]
     private overlayChildViews = () => {
-        console.log(this.overlayViews.length);
-        return [
-            ...this.overlayViews
-        ];
+        return [...this.overlayViews];
     }
 
     public static AddCustomLayout(doc: Doc, dataKey: string): () => void {
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index b9ee588dd..ff96bd993 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -278,6 +278,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
                 panX: 0,
                 panY: 0,
                 backgroundColor: this.props.container.isAnnotationOverlay ? undefined : "white",
+                defaultBackgroundColor: this.props.container.isAnnotationOverlay ? undefined : "white",
                 width: bounds.width,
                 height: bounds.height,
                 title: e.key === "s" || e.key === "S" ? "-summary-" : "a nested collection",
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 3b6c443c2..ee596c841 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -8,6 +8,7 @@ import { DocumentView, DocumentViewProps, positionSchema } from "./DocumentView"
 import "./DocumentView.scss";
 import React = require("react");
 import { Doc } from "../../../new_fields/Doc";
+import { returnEmptyString } from "../../../Utils";
 
 export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
     x?: number;
@@ -69,6 +70,11 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
         return undefined;
     }
 
+    @computed
+    get clusterColor() { return this.props.backgroundColor(this.props.Document); }
+
+    clusterColorFunc = (doc: Doc) => this.clusterColor;
+
     render() {
         const hasPosition = this.props.x !== undefined || this.props.y !== undefined;
         return (
@@ -77,7 +83,10 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                     transformOrigin: "left top",
                     position: "absolute",
                     backgroundColor: "transparent",
-                    boxShadow: this.props.Document.z ? `#9c9396 ${StrCast(this.props.Document.boxShadow, "10px 10px 0.9vw")}` : undefined,
+                    boxShadow: this.props.Document.z ? `#9c9396  ${StrCast(this.props.Document.boxShadow, "10px 10px 0.9vw")}` :
+                        this.clusterColor ? (
+                            this.props.Document.isBackground ? `0px 0px 50px 50px ${this.clusterColor}` :
+                                `${this.clusterColor} ${StrCast(this.props.Document.boxShadow, `0vw 0vw ${50 / this.props.ContentScaling()}px`)}`) : undefined,
                     borderRadius: this.borderRounding(),
                     transform: this.transform,
                     transition: hasPosition ? "transform 1s" : StrCast(this.props.Document.transition),
@@ -88,6 +97,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                 <DocumentView {...this.props}
                     ContentScaling={this.contentScaling}
                     ScreenToLocalTransform={this.getTransform}
+                    backgroundColor={this.clusterColorFunc}
                     PanelWidth={this.panelWidth}
                     PanelHeight={this.panelHeight}
                     animateBetweenIcon={this.animateBetweenIcon}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 16ae5471d..ae6a01ab4 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,6 +1,6 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
 import * as fa from '@fortawesome/free-solid-svg-icons';
-import { action, computed, IReactionDisposer, reaction, runInAction } from "mobx";
+import { action, computed, IReactionDisposer, reaction, runInAction, trace } from "mobx";
 import { observer } from "mobx-react";
 import * as rp from "request-promise";
 import { Doc, DocListCast, DocListCastAsync, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc";
@@ -95,6 +95,7 @@ export interface DocumentViewProps {
     addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => void;
     collapseToPoint?: (scrpt: number[], expandedDocs: Doc[] | undefined) => void;
     zoomToScale: (scale: number) => void;
+    backgroundColor: (doc: Doc) => string;
     getScale: () => number;
     animateBetweenIcon?: (iconPos: number[], startTime: number, maximizing: boolean) => void;
     ChromeHeight?: () => number;
@@ -675,12 +676,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         // to determine the render JSX string, otherwise the layout field should directly contain a JSX layout string.
         return this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document;
     }
+
     render() {
-        if (this.Document.hidden) {
-            return null;
-        }
-        let self = this;
-        let backgroundColor = StrCast(this.layoutDoc.backgroundColor);
+        let backgroundColor = this.props.backgroundColor(this.props.Document) || StrCast(this.layoutDoc.backgroundColor);
         let foregroundColor = StrCast(this.layoutDoc.color);
         var nativeWidth = this.nativeWidth > 0 && !BoolCast(this.props.Document.ignoreAspect) ? `${this.nativeWidth}px` : "100%";
         var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%";
@@ -695,8 +693,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             });
         }
         let showTextTitle = showTitle && StrCast(this.layoutDoc.layout).startsWith("<FormattedTextBox") ? showTitle : undefined;
-        let colors = ["#da42429e", "#31ea318c", "#8c4000", "#4a7ae2c4", "#d809ff", "#ff7601", "#1dffff", "yellow", "#1b8231f2", "#000000ad"];
-        let groupCol = colors[NumCast(this.props.Document.cluster) % colors.length];
         return (
             <div className={`documentView-node${this.topMost ? "-topmost" : ""}`}
                 ref={this._mainCont}
@@ -705,9 +701,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                     color: foregroundColor,
                     outlineColor: "maroon",
                     outlineStyle: "dashed",
-                    boxShadow: this.layoutDoc.isBackground ?
-                        `0px 0px 50px 50px ${groupCol}` :
-                        `${groupCol} ${StrCast(this.props.Document.boxShadow, `0vw 0vw ${50 / this.props.ContentScaling()}px`)}`,
                     outlineWidth: BoolCast(this.layoutDoc.libraryBrush) && !StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
                         `${this.props.ScreenToLocalTransform().Scale}px` : "0px",
                     marginLeft: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
@@ -717,7 +710,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                     border: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
                         `dashed maroon ${this.props.ScreenToLocalTransform().Scale}px` : undefined,
                     borderRadius: "inherit",
-                    background: this.layoutDoc.isBackground ? groupCol : backgroundColor,
+                    background: backgroundColor,
                     width: nativeWidth,
                     height: nativeHeight,
                     transform: `scale(${this.props.ContentScaling()})`,
diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx
index 11f3eb846..e2d8daea9 100644
--- a/src/client/views/presentationview/PresentationElement.tsx
+++ b/src/client/views/presentationview/PresentationElement.tsx
@@ -9,7 +9,7 @@ import { Id } from "../../../new_fields/FieldSymbols";
 import { List } from "../../../new_fields/List";
 import { listSpec } from "../../../new_fields/Schema";
 import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types";
-import { Utils, returnFalse, emptyFunction, returnOne } from "../../../Utils";
+import { Utils, returnFalse, emptyFunction, returnOne, returnEmptyString } from "../../../Utils";
 import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager";
 import { SelectionManager } from "../../util/SelectionManager";
 import { ContextMenu } from "../ContextMenu";
@@ -843,6 +843,7 @@ export default class PresentationElement extends React.Component<PresentationEle
                     PanelWidth={() => 350}
                     PanelHeight={() => 90}
                     focus={emptyFunction}
+                    backgroundColor={returnEmptyString}
                     selectOnLoad={false}
                     parentActive={returnFalse}
                     whenActiveChanged={returnFalse}
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index 0390359b3..1b9bba5c6 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -7,7 +7,7 @@ import { observer } from "mobx-react";
 import { Doc, DocListCast, HeightSym, WidthSym } from "../../../new_fields/Doc";
 import { Id } from "../../../new_fields/FieldSymbols";
 import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
-import { emptyFunction, returnFalse, returnOne, Utils } from "../../../Utils";
+import { emptyFunction, returnFalse, returnOne, Utils, returnEmptyString } from "../../../Utils";
 import { DocumentType } from "../../documents/Documents";
 import { DocumentManager } from "../../util/DocumentManager";
 import { SetupDrag, DragManager } from "../../util/DragManager";
@@ -223,6 +223,7 @@ export class SearchItem extends React.Component<SearchItemProps> {
                     PanelWidth={returnXDimension}
                     PanelHeight={returnYDimension}
                     focus={emptyFunction}
+                    backgroundColor={returnEmptyString}
                     selectOnLoad={false}
                     parentActive={returnFalse}
                     whenActiveChanged={returnFalse}
-- 
cgit v1.2.3-70-g09d2


From bbca58e2ff087bbd4bb2ee12e6c4567e146450e3 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 3 Aug 2019 23:47:26 -0400
Subject: fixed css for stacking views so that height/width are claculated
 correctly.

---
 .../views/collections/CollectionSchemaView.tsx     |  6 +++--
 .../views/collections/CollectionStackingView.scss  |  4 ++++
 .../views/collections/CollectionStackingView.tsx   | 26 ++++++++++------------
 3 files changed, 20 insertions(+), 16 deletions(-)

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

diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 8218877ba..2d4c88b94 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -974,14 +974,16 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
         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>;
-        return (<div className="collectionSchemaView-previewRegion" style={{ width: this.props.width(), height: "100%" }}>
+        return (<div className="collectionSchemaView-previewRegion"
+            style={{ width: this.props.width(), height: this.props.height() }}>
             {!this.props.Document || !this.props.width ? (null) : (
                 <div className="collectionSchemaView-previewDoc"
                     style={{
                         transform: `translate(${this.centeringOffset}px, 0px)`,
                         borderRadius: this.borderRounding,
                         display: "inline",
-                        height: "100%"
+                        height: this.props.height(),
+                        width: this.props.width()
                     }}>
                     <DocumentView
                         DataDoc={this.props.DataDocument}
diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss
index 015955816..271ad2d58 100644
--- a/src/client/views/collections/CollectionStackingView.scss
+++ b/src/client/views/collections/CollectionStackingView.scss
@@ -9,6 +9,10 @@
     overflow-y: auto;
     flex-wrap: wrap;
     transition: top .5s;
+    .collectionSchemaView-previewDoc {
+        height: 100%;
+        position: absolute;
+    }
 
     .collectionStackingView-docView-container {
         width: 45%;
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 9741b9e89..d7c3ac3b8 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -46,16 +46,18 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         return this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document;
     }
 
+    @computed
+    get SectionFilter() { return this.singleColumn ? StrCast(this.props.Document.sectionFilter) : "" }
+
     get Sections() {
-        let sectionFilter = StrCast(this.props.Document.sectionFilter);
         let sectionHeaders = this.sectionHeaders;
         if (!sectionHeaders) {
             this.props.Document.sectionHeaders = sectionHeaders = new List();
         }
         let fields = new Map<SchemaHeaderField, Doc[]>(sectionHeaders.map(sh => [sh, []]));
-        if (sectionFilter) {
+        if (this.SectionFilter) {
             this.filteredChildren.map(d => {
-                let sectionValue = (d[sectionFilter] ? d[sectionFilter] : `NO ${sectionFilter.toUpperCase()} VALUE`) as object;
+                let sectionValue = (d[this.SectionFilter] ? d[this.SectionFilter] : `NO ${this.SectionFilter.toUpperCase()} VALUE`) as object;
                 // the next five lines ensures that floating point rounding errors don't create more than one section -syip
                 let parsed = parseInt(sectionValue.toString());
                 let castedSectionValue: any = sectionValue;
@@ -64,17 +66,17 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                 }
 
                 // look for if header exists already
-                let existingHeader = sectionHeaders!.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${sectionFilter.toUpperCase()} VALUE`));
+                let existingHeader = sectionHeaders!.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.SectionFilter.toUpperCase()} VALUE`));
                 if (existingHeader) {
                     fields.get(existingHeader)!.push(d);
                 }
                 else {
-                    let newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${sectionFilter.toUpperCase()} VALUE`);
+                    let newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${this.SectionFilter.toUpperCase()} VALUE`);
                     fields.set(newSchemaHeader, [d]);
                     sectionHeaders!.push(newSchemaHeader);
                 }
             });
-        }
+        } else fields.clear();
         return fields;
     }
 
@@ -94,7 +96,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
 
         // reset section headers when a new filter is inputted
         this._sectionFilterDisposer = reaction(
-            () => StrCast(this.props.Document.sectionFilter),
+            () => this.SectionFilter,
             () => {
                 this.props.Document.sectionHeaders = new List();
             }
@@ -232,7 +234,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         });
     }
     section = (heading: SchemaHeaderField | undefined, docList: Doc[]) => {
-        let key = StrCast(this.props.Document.sectionFilter);
+        let key = this.SectionFilter;
         let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined;
         let types = docList.length ? docList.map(d => typeof d[key]) : this.childDocs.map(d => typeof d[key]);
         if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) {
@@ -294,14 +296,10 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         return (
             <div className="collectionStackingView"
                 ref={this.createRef} onDrop={this.onDrop.bind(this)} onWheel={(e: React.WheelEvent) => e.stopPropagation()} >
-                {/* {sectionFilter as boolean ? [
-                    ["width > height", this.filteredChildren.filter(f => f[WidthSym]() >= 1 + f[HeightSym]())],
-                    ["width = height", this.filteredChildren.filter(f => Math.abs(f[WidthSym]() - f[HeightSym]()) < 1)],
-                    ["height > width", this.filteredChildren.filter(f => f[WidthSym]() + 1 <= f[HeightSym]())]]. */}
-                {this.props.Document.sectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc).
+                {this.SectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc).
                     map(section => this.section(section[0], section[1])) :
                     this.section(undefined, this.filteredChildren)}
-                {(this.props.Document.sectionFilter && (this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.CollectionView.props.Document.chromeStatus !== 'disabled')) ?
+                {(this.SectionFilter && (this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.CollectionView.props.Document.chromeStatus !== 'disabled')) ?
                     <div key={`${this.props.Document[Id]}-addGroup`} className="collectionStackingView-addGroupButton"
                         style={{ width: (this.columnWidth / (headings.length + ((this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0))) - 10, marginTop: 10 }}>
                         <EditableView {...editableViewProps} />
-- 
cgit v1.2.3-70-g09d2


From 02346eabdefd428ca23d6a3fbefdcd51ef62b738 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 4 Aug 2019 01:17:29 -0400
Subject: fixed errors/warnings

---
 src/client/apis/youtube/YoutubeBox.tsx             |   8 +-
 src/client/views/InkingControl.tsx                 |   4 +-
 src/client/views/TemplateMenu.tsx                  |   2 +-
 .../views/collections/CollectionSchemaCells.tsx    |   4 +-
 .../views/collections/CollectionSchemaHeaders.tsx  |   2 +-
 .../views/collections/CollectionSchemaView.tsx     |   5 +-
 .../views/collections/CollectionStackingView.tsx   | 116 +++++++++------------
 src/client/views/collections/CollectionView.tsx    |  11 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  23 ++--
 src/client/views/nodes/ButtonBox.tsx               |   2 +-
 src/client/views/nodes/DocumentView.tsx            |   2 +-
 src/client/views/nodes/PDFBox.tsx                  |   4 +-
 src/client/views/search/FilterBox.tsx              |   2 +-
 src/client/views/search/SearchItem.tsx             |   2 +-
 src/client/views/search/ToggleBar.tsx              |   2 +-
 src/new_fields/Doc.ts                              |   4 +-
 16 files changed, 82 insertions(+), 111 deletions(-)

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

diff --git a/src/client/apis/youtube/YoutubeBox.tsx b/src/client/apis/youtube/YoutubeBox.tsx
index dc142802c..d73988bb8 100644
--- a/src/client/apis/youtube/YoutubeBox.tsx
+++ b/src/client/apis/youtube/YoutubeBox.tsx
@@ -57,7 +57,7 @@ export class YoutubeBox extends React.Component<FieldViewProps> {
         if (awaitedBackUp) {
 
 
-            let jsonList = await DocListCastAsync(awaitedBackUp!.json);
+            let jsonList = await DocListCastAsync(awaitedBackUp.json);
             let jsonDetailList = await DocListCastAsync(awaitedDetails!.json);
 
             if (jsonList!.length !== 0) {
@@ -76,8 +76,8 @@ export class YoutubeBox extends React.Component<FieldViewProps> {
                     let videoDescription = StrCast(snippet!.description);
                     let pusblishDate = (this.roundPublishTime(StrCast(snippet!.publishedAt)))!;
                     let channelTitle = StrCast(snippet!.channelTitle);
-                    let duration: string;
-                    let viewCount: string;
+                    let duration: string = "";
+                    let viewCount: string = "";
                     if (jsonDetailList!.length !== 0) {
                         let contentDetails = await Cast(jsonDetailList![index].contentDetails, Doc);
                         let statistics = await Cast(jsonDetailList![index].statistics, Doc);
@@ -85,7 +85,7 @@ export class YoutubeBox extends React.Component<FieldViewProps> {
                         viewCount = this.abbreviateViewCount(parseInt(StrCast(statistics!.viewCount)))!;
                     }
                     index = index + 1;
-                    let newTemplate: VideoTemplate = { videoId: id, videoTitle: videoTitle, thumbnailUrl: thumbnailUrl, publishDate: pusblishDate, channelTitle: channelTitle, videoDescription: videoDescription, duration: duration!, viewCount: viewCount! };
+                    let newTemplate: VideoTemplate = { videoId: id, videoTitle: videoTitle, thumbnailUrl: thumbnailUrl, publishDate: pusblishDate, channelTitle: channelTitle, videoDescription: videoDescription, duration: duration, viewCount: viewCount };
                     runInAction(() => this.curVideoTemplates.push(newTemplate));
                 }
             }
diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index 58c83915b..3f40642b5 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -1,5 +1,5 @@
 import { observable, action, computed, runInAction } from "mobx";
-import { ColorState } from 'react-color';
+import { ColorResult } from 'react-color';
 import React = require("react");
 import { observer } from "mobx-react";
 import "./InkingControl.scss";
@@ -41,7 +41,7 @@ export class InkingControl extends React.Component {
     }
 
     @undoBatch
-    switchColor = action((color: ColorState): void => {
+    switchColor = action((color: ColorResult): void => {
         this._selectedColor = color.hex + (color.rgb.a !== undefined ? this.decimalToHexString(Math.round(color.rgb.a * 255)) : "ff");
         if (InkingControl.Instance.selectedTool === InkTool.None) {
             if (MainOverlayTextBox.Instance.SetColor(color.hex)) return;
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index 6dd908445..393e97a7e 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -68,7 +68,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
                 }
             }, 10);
         } else if (topDocView.props.ContainingCollectionView) {
-            let collView = topDocView.props.ContainingCollectionView!;
+            let collView = topDocView.props.ContainingCollectionView;
             let [sx, sy] = xf.inverse().transformPoint(0, 0);
             let [x, y] = collView.props.ScreenToLocalTransform().transformPoint(sx, sy);
             topDoc.x = x;
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 4ff65b277..7e3061354 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -175,11 +175,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 = "collectionSchemaView-cellContainer doc-drag-over";
+                dragRef.current!.className = "collectionSchemaView-cellContainer doc-drag-over";
             }
         };
         let onPointerLeave = (e: React.PointerEvent): void => {
-            dragRef!.current!.className = "collectionSchemaView-cellContainer";
+            dragRef.current!.className = "collectionSchemaView-cellContainer";
         };
 
         let contents: any = "incorrect type";
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index dfd65770e..d24f63fbb 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -13,7 +13,7 @@ import { faFile } from "@fortawesome/free-regular-svg-icons";
 import { SchemaHeaderField, RandomPastel, PastelSchemaPalette } from "../../../new_fields/SchemaHeaderField";
 import { undoBatch } from "../../util/UndoManager";
 
-library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faFile, faSortAmountDown, faSortAmountUp, faTimes);
+library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faFile as any, faSortAmountDown, faSortAmountUp, faTimes);
 
 export interface HeaderProps {
     keyValue: SchemaHeaderField;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 2d4c88b94..75787c0a8 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -303,14 +303,13 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             return resized;
         }, [] as { "id": string, "value": number }[]);
     }
-
-    @computed get sorted(): { "id": string, "desc": boolean }[] {
+    @computed get sorted(): { "id": string, "desc"?: true }[] {
         return this.columns.reduce((sorted, shf) => {
             if (shf.desc) {
                 sorted.push({ "id": shf.heading, "desc": shf.desc });
             }
             return sorted;
-        }, [] as { "id": string, "desc": boolean }[]);
+        }, [] as { "id": string, "desc"?: true }[]);
     }
 
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index d7c3ac3b8..4a751c84c 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -1,26 +1,25 @@
 import React = require("react");
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, computed, IReactionDisposer, reaction, untracked, observable, runInAction } from "mobx";
+import { CursorProperty } from "csstype";
+import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, HeightSym, WidthSym, DocListCast } from "../../../new_fields/Doc";
+import Switch from 'rc-switch';
+import { Doc, HeightSym, WidthSym } from "../../../new_fields/Doc";
 import { Id } from "../../../new_fields/FieldSymbols";
-import { BoolCast, NumCast, Cast, StrCast } from "../../../new_fields/Types";
-import { emptyFunction, Utils, returnTrue } from "../../../Utils";
-import { CollectionSchemaPreview } from "./CollectionSchemaView";
-import "./CollectionStackingView.scss";
-import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView";
-import { undoBatch } from "../../util/UndoManager";
-import { DragManager } from "../../util/DragManager";
+import { List } from "../../../new_fields/List";
+import { listSpec } from "../../../new_fields/Schema";
+import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
+import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types";
+import { emptyFunction } from "../../../Utils";
 import { DocumentType } from "../../documents/Documents";
+import { DragManager } from "../../util/DragManager";
 import { Transform } from "../../util/Transform";
-import { CursorProperty } from "csstype";
-import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn";
-import { listSpec } from "../../../new_fields/Schema";
-import { SchemaHeaderField, RandomPastel } from "../../../new_fields/SchemaHeaderField";
-import { List } from "../../../new_fields/List";
+import { undoBatch } from "../../util/UndoManager";
 import { EditableView } from "../EditableView";
-import { CollectionViewProps } from "./CollectionBaseView";
-import Switch from 'rc-switch';
+import { CollectionSchemaPreview } from "./CollectionSchemaView";
+import "./CollectionStackingView.scss";
+import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn";
+import { CollectionSubView } from "./CollectionSubView";
 
 @observer
 export class CollectionStackingView extends CollectionSubView(doc => doc) {
@@ -32,13 +31,13 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     _columnStart: number = 0;
     @observable private cursor: CursorProperty = "grab";
     get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); }
-    @computed get chromeCollapsed() { return this.props.chromeCollapsed; }
     @computed get xMargin() { return NumCast(this.props.Document.xMargin, 2 * this.gridGap); }
     @computed get yMargin() { return NumCast(this.props.Document.yMargin, 2 * this.gridGap); }
     @computed get gridGap() { return NumCast(this.props.Document.gridGap, 10); }
     @computed get singleColumn() { return BoolCast(this.props.Document.singleColumn, true); }
     @computed get columnWidth() { return this.singleColumn ? (this.props.PanelWidth() / (this.props as any).ContentScaling() - 2 * this.xMargin) : Math.min(this.props.PanelWidth() - 2 * this.xMargin, NumCast(this.props.Document.columnWidth, 250)); }
     @computed get filteredChildren() { return this.childDocs.filter(d => !d.isMinimized); }
+    @computed get sectionFilter() { return this.singleColumn ? StrCast(this.props.Document.sectionFilter) : ""; }
 
     get layoutDoc() {
         // if this document's layout field contains a document (ie, a rendering template), then we will use that
@@ -46,37 +45,32 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         return this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document;
     }
 
-    @computed
-    get SectionFilter() { return this.singleColumn ? StrCast(this.props.Document.sectionFilter) : "" }
 
     get Sections() {
-        let sectionHeaders = this.sectionHeaders;
-        if (!sectionHeaders) {
-            this.props.Document.sectionHeaders = sectionHeaders = new List();
+        if (!this.sectionFilter) return new Map<SchemaHeaderField, Doc[]>();
+
+        if (this.sectionHeaders === undefined) {
+            this.props.Document.sectionHeaders = new List<SchemaHeaderField>();
         }
-        let fields = new Map<SchemaHeaderField, Doc[]>(sectionHeaders.map(sh => [sh, []]));
-        if (this.SectionFilter) {
-            this.filteredChildren.map(d => {
-                let sectionValue = (d[this.SectionFilter] ? d[this.SectionFilter] : `NO ${this.SectionFilter.toUpperCase()} VALUE`) as object;
-                // the next five lines ensures that floating point rounding errors don't create more than one section -syip
-                let parsed = parseInt(sectionValue.toString());
-                let castedSectionValue: any = sectionValue;
-                if (!isNaN(parsed)) {
-                    castedSectionValue = parsed;
-                }
+        const sectionHeaders = this.sectionHeaders!;
+        let fields = new Map<SchemaHeaderField, Doc[]>(sectionHeaders.map(sh => [sh, []] as [SchemaHeaderField, []]));
+        this.filteredChildren.map(d => {
+            let sectionValue = (d[this.sectionFilter] ? d[this.sectionFilter] : `NO ${this.sectionFilter.toUpperCase()} VALUE`) as object;
+            // the next five lines ensures that floating point rounding errors don't create more than one section -syip
+            let parsed = parseInt(sectionValue.toString());
+            let castedSectionValue = !isNaN(parsed) ? parsed : sectionValue;
 
-                // look for if header exists already
-                let existingHeader = sectionHeaders!.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.SectionFilter.toUpperCase()} VALUE`));
-                if (existingHeader) {
-                    fields.get(existingHeader)!.push(d);
-                }
-                else {
-                    let newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${this.SectionFilter.toUpperCase()} VALUE`);
-                    fields.set(newSchemaHeader, [d]);
-                    sectionHeaders!.push(newSchemaHeader);
-                }
-            });
-        } else fields.clear();
+            // look for if header exists already
+            let existingHeader = sectionHeaders.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.sectionFilter.toUpperCase()} VALUE`));
+            if (existingHeader) {
+                fields.get(existingHeader)!.push(d);
+            }
+            else {
+                let newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${this.sectionFilter.toUpperCase()} VALUE`);
+                fields.set(newSchemaHeader, [d]);
+                sectionHeaders.push(newSchemaHeader);
+            }
+        });
         return fields;
     }
 
@@ -96,10 +90,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
 
         // reset section headers when a new filter is inputted
         this._sectionFilterDisposer = reaction(
-            () => this.SectionFilter,
-            () => {
-                this.props.Document.sectionHeaders = new List();
-            }
+            () => this.sectionFilter,
+            () => this.props.Document.sectionHeaders = new List()
         );
     }
     componentWillUnmount() {
@@ -186,8 +178,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     @undoBatch
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
-        let targInd = -1;
         let where = [de.x, de.y];
+        let targInd = -1;
         if (de.data instanceof DragManager.DocumentDragData) {
             this._docXfs.map((cd, i) => {
                 let pos = cd.dxf().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap);
@@ -233,8 +225,9 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             }
         });
     }
+    headings = () => Array.from(this.Sections.keys());
     section = (heading: SchemaHeaderField | undefined, docList: Doc[]) => {
-        let key = this.SectionFilter;
+        let key = this.sectionFilter;
         let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined;
         let types = docList.length ? docList.map(d => typeof d[key]) : this.childDocs.map(d => typeof d[key]);
         if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) {
@@ -245,7 +238,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         return <CollectionStackingViewFieldColumn
             key={heading ? heading.heading : ""}
             cols={cols}
-            headings={() => Array.from(this.Sections.keys())}
+            headings={this.headings}
             heading={heading ? heading.heading : ""}
             headingObject={heading}
             docList={docList}
@@ -254,16 +247,13 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             createDropTarget={this.createDropTarget}
             screenToLocalTransform={this.props.ScreenToLocalTransform}
         />;
-
     }
 
     @action
     addGroup = (value: string) => {
-        if (value) {
-            if (this.sectionHeaders) {
-                this.sectionHeaders.push(new SchemaHeaderField(value));
-                return true;
-            }
+        if (value && this.sectionHeaders) {
+            this.sectionHeaders.push(new SchemaHeaderField(value));
+            return true;
         }
         return false;
     }
@@ -276,11 +266,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
     }
 
     onToggle = (checked: Boolean) => {
-        if (checked) {
-            this.props.CollectionView.props.Document.chromeStatus = 'collapsed';
-        } else {
-            this.props.CollectionView.props.Document.chromeStatus = 'view-mode';
-        }
+        this.props.CollectionView.props.Document.chromeSatus = checked ? "collapsed" : "view-mode";
     }
 
     render() {
@@ -296,10 +282,10 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         return (
             <div className="collectionStackingView"
                 ref={this.createRef} onDrop={this.onDrop.bind(this)} onWheel={(e: React.WheelEvent) => e.stopPropagation()} >
-                {this.SectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc).
-                    map(section => this.section(section[0], section[1])) :
+                {this.sectionFilter ? Array.from(this.Sections.entries()).sort(this.sortFunc).
+                    map((section: [SchemaHeaderField, Doc[]]) => this.section(section[0], section[1])) :
                     this.section(undefined, this.filteredChildren)}
-                {(this.SectionFilter && (this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.CollectionView.props.Document.chromeStatus !== 'disabled')) ?
+                {(this.sectionFilter && (this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.CollectionView.props.Document.chromeStatus !== 'disabled')) ?
                     <div key={`${this.props.Document[Id]}-addGroup`} className="collectionStackingView-addGroupButton"
                         style={{ width: (this.columnWidth / (headings.length + ((this.props.CollectionView.props.Document.chromeStatus !== 'view-mode' && this.props.CollectionView.props.Document.chromeStatus !== 'disabled') ? 1 : 0))) - 10, marginTop: 10 }}>
                         <EditableView {...editableViewProps} />
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 57dc5879b..f59fee985 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -20,16 +20,7 @@ import { CollectionTreeView } from "./CollectionTreeView";
 import { CollectionViewBaseChrome } from './CollectionViewChromes';
 export const COLLECTION_BORDER_WIDTH = 2;
 
-library.add(faTh);
-library.add(faTree);
-library.add(faSquare);
-library.add(faProjectDiagram);
-library.add(faSignature);
-library.add(faThList);
-library.add(faFingerprint);
-library.add(faColumns);
-library.add(faEllipsisV);
-library.add(faImage, faEye);
+library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faEllipsisV, faImage, faEye as any);
 
 @observer
 export class CollectionView extends React.Component<FieldViewProps> {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index b4d065d26..c943fac74 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -40,7 +40,7 @@ import v5 = require("uuid/v5");
 import { setScheduler } from "bluebird";
 import { DocumentType, Docs } from "../../../documents/Documents";
 
-library.add(faEye, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload);
+library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload);
 
 export const panZoomSchema = createSchema({
     panX: "number",
@@ -206,8 +206,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             let cy = NumCast(cd.y) - this._clusterDistance;
             let cw = NumCast(cd.width) + 2 * this._clusterDistance;
             let ch = NumCast(cd.height) + 2 * this._clusterDistance;
-            if (!cd.z && this.intersectRect({ left: cx, top: cy, width: cw, height: ch }, { left: probe[0], top: probe[1], width: 1, height: 1 }))
+            if (!cd.z && this.intersectRect({ left: cx, top: cy, width: cw, height: ch }, { left: probe[0], top: probe[1], width: 1, height: 1 })) {
                 return NumCast(cd.cluster);
+            }
             return cluster;
         }, -1);
         if (cluster !== -1) {
@@ -236,20 +237,20 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     updateClusters() {
         this.sets.length = 0;
         this.childDocs.map(c => {
-            let included = []
+            let included = [];
             for (let i = 0; i < this.sets.length; i++) {
-                for (let j = 0; j < this.sets[i].length; j++) {
-                    if (this.boundsOverlap(c, this.sets[i][j])) {
+                for (let member of this.sets[i]) {
+                    if (this.boundsOverlap(c, member)) {
                         included.push(i);
                         break;
                     }
                 }
             }
-            if (included.length === 0)
+            if (included.length === 0) {
                 this.sets.push([c]);
-            else if (included.length === 1)
+            } else if (included.length === 1) {
                 this.sets[included[0]].push(c);
-            else {
+            } else {
                 this.sets[included[0]].push(c);
                 for (let s = 1; s < included.length; s++) {
                     this.sets[included[0]].push(...this.sets[included[s]]);
@@ -257,11 +258,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
                 }
             }
         });
-        for (let s = 0; s < this.sets.length; s++) {
-            for (let i = 0; i < this.sets[s].length; i++) {
-                this.sets[s][i].cluster = s;
-            }
-        }
+        this.sets.map((set, i) => set.map(member => member.cluster = i));
     }
 
     getClusterColor = (doc: Doc) => {
diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx
index e2c559c9a..640795789 100644
--- a/src/client/views/nodes/ButtonBox.tsx
+++ b/src/client/views/nodes/ButtonBox.tsx
@@ -16,7 +16,7 @@ import './ButtonBox.scss';
 import { observer } from 'mobx-react';
 import { DocumentIconContainer } from './DocumentIcon';
 
-library.add(faEdit);
+library.add(faEdit as any);
 
 const ButtonSchema = createSchema({
     onClick: ScriptField,
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 0347fc9b2..4528cf94d 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -95,7 +95,7 @@ export interface DocumentViewProps {
     addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => void;
     collapseToPoint?: (scrpt: number[], expandedDocs: Doc[] | undefined) => void;
     zoomToScale: (scale: number) => void;
-    backgroundColor: (doc: Doc) => string;
+    backgroundColor: (doc: Doc) => string | undefined;
     getScale: () => number;
     animateBetweenIcon?: (iconPos: number[], startTime: number, maximizing: boolean) => void;
     ChromeHeight?: () => number;
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index fa072aecf..a49709e83 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -152,9 +152,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
     }
 
     scrollTo(y: number) {
-        if (this._mainCont.current) {
-            this._mainCont.current.scrollTo({ top: Math.max(y - (this._mainCont.current!.offsetHeight / 2), 0), behavior: "auto" });
-        }
+        this._mainCont.current && this._mainCont.current.scrollTo({ top: Math.max(y - (this._mainCont.current.offsetHeight / 2), 0), behavior: "auto" });
     }
 
     settingsPanel() {
diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx
index 995ddd5c3..3e8582d61 100644
--- a/src/client/views/search/FilterBox.tsx
+++ b/src/client/views/search/FilterBox.tsx
@@ -384,7 +384,7 @@ export class FilterBox extends React.Component {
                     <div className="active-icon description">Collection Filters Active</div>
                 </div> : undefined}
             </div>
-        )
+        );
     }
 
     // Useful queries:
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index 1b9bba5c6..48eb87251 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -134,7 +134,7 @@ export class LinkContextMenu extends React.Component<LinkMenuProps> {
                 <div className="collection"><a onMouseEnter={this.highlightDoc(this.props.doc1)} onMouseLeave={this.unHighlightDoc(this.props.doc1)} onClick={this.getOnClick(this.props.doc1)}>Doc 1: {this.props.doc2.title}</a></div>
                 <div><a onMouseEnter={this.highlightDoc(this.props.doc2)} onMouseLeave={this.unHighlightDoc(this.props.doc2)} onClick={this.getOnClick(this.props.doc2)}>Doc 2: {this.props.doc1.title}</a></div>
             </div>
-        )
+        );
     }
 
 }
diff --git a/src/client/views/search/ToggleBar.tsx b/src/client/views/search/ToggleBar.tsx
index a30104089..ed5ecd3ba 100644
--- a/src/client/views/search/ToggleBar.tsx
+++ b/src/client/views/search/ToggleBar.tsx
@@ -59,7 +59,7 @@ export class ToggleBar extends React.Component<ToggleBarProps>{
         this._forwardTimeline.play();
         this._forwardTimeline.reverse();
         this.props.handleChange();
-        console.log(this.props.getStatus())
+        console.log(this.props.getStatus());
     }
 
     @action.bound
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index b081588a3..c01f4e8cf 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -358,7 +358,7 @@ export namespace Doc {
         let docExtensionForField = doc[fieldKey + "_ext"] as Doc;
         if (docExtensionForField === undefined) {
             setTimeout(() => {
-                CreateDocumentExtensionForField(doc, field);
+                CreateDocumentExtensionForField(doc, fieldKey);
             }, 0);
         } else if (doc instanceof Doc) { // backward compatibility -- add fields for docs that don't have them already
             docExtensionForField.extendsDoc === undefined && setTimeout(() => docExtensionForField.extendsDoc = doc, 0);
@@ -535,7 +535,7 @@ export namespace Doc {
                 d.layout = detailLayout;
                 d.nativeWidth = d.nativeHeight = undefined;
                 if (detailLayout instanceof Doc) {
-                    let delegDetailLayout = Doc.MakeDelegate(detailLayout) as Doc;
+                    let delegDetailLayout = Doc.MakeDelegate(detailLayout);
                     d.layout = delegDetailLayout;
                     delegDetailLayout.layout = await delegDetailLayout.detailedLayout;
                 }
-- 
cgit v1.2.3-70-g09d2


From ebddce0975fa7e224e022cc075eee71abeacbe1d Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 7 Aug 2019 23:27:21 -0400
Subject: changed pdfs to render regions as collections.  changed libraryBrush
 implementation.

---
 src/client/views/SearchItem.tsx                    |  6 ++--
 .../views/collections/CollectionDockingView.tsx    |  2 +-
 .../views/collections/CollectionSchemaView.tsx     |  2 +-
 .../views/collections/CollectionTreeView.tsx       |  8 ++---
 src/client/views/nodes/DocumentView.tsx            | 37 ++++++++++-----------
 src/client/views/nodes/FormattedTextBox.tsx        |  2 +-
 src/client/views/pdf/PDFViewer.tsx                 |  3 +-
 src/client/views/pdf/Page.tsx                      |  9 ++---
 .../views/presentationview/PresentationElement.tsx |  4 +--
 src/client/views/search/SearchItem.tsx             | 38 +++++++---------------
 src/new_fields/Doc.ts                              | 18 ++++++++++
 src/new_fields/util.ts                             |  1 -
 src/scraping/buxton/scraper.py                     |  9 ++---
 13 files changed, 65 insertions(+), 74 deletions(-)

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

diff --git a/src/client/views/SearchItem.tsx b/src/client/views/SearchItem.tsx
index 13e4b88f7..fd4b2420d 100644
--- a/src/client/views/SearchItem.tsx
+++ b/src/client/views/SearchItem.tsx
@@ -37,12 +37,10 @@ export class SearchItem extends React.Component<SearchProps> {
         return <FontAwesomeIcon icon={button} className="documentView-minimizedIcon" />;
     }
     onPointerEnter = (e: React.PointerEvent) => {
-        this.props.doc.libraryBrush = true;
-        Doc.SetOnPrototype(this.props.doc, "protoBrush", true);
+        Doc.BrushDoc(this.props.doc);
     }
     onPointerLeave = (e: React.PointerEvent) => {
-        this.props.doc.libraryBrush = false;
-        Doc.SetOnPrototype(this.props.doc, "protoBrush", false);
+        Doc.UnBrushDoc(this.props.doc);
     }
 
     collectionRef = React.createRef<HTMLDivElement>();
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index f559480ed..3af92cbe3 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -405,7 +405,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
                             handlers: { dragComplete: emptyFunction },
                             hideSource: false
                         });
-                    }}><FontAwesomeIcon icon="file" size="lg" /></span>, dragSpan);
+                    }}><FontAwesomeIcon icon="file" color={["white", "maroon", "blue"][Doc.IsBrushedDegree(doc)]} size="lg" /></span>, dragSpan);
                 ReactDOM.render(<ParentDocSelector Document={doc} addDocTab={doc => CollectionDockingView.Instance.AddTab(stack, doc, dataDoc)} />, upDiv);
                 tab.reactComponents = [dragSpan, upDiv];
                 tab.element.append(dragSpan);
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 75787c0a8..ebfa737be 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -50,7 +50,7 @@ const columnTypes: Map<string, ColumnType> = new Map([
     ["title", ColumnType.String],
     ["x", ColumnType.Number], ["y", ColumnType.Number], ["width", ColumnType.Number], ["height", ColumnType.Number],
     ["nativeWidth", ColumnType.Number], ["nativeHeight", ColumnType.Number], ["isPrototype", ColumnType.Boolean],
-    ["page", ColumnType.Number], ["curPage", ColumnType.Number], ["libraryBrush", ColumnType.Boolean], ["zIndex", ColumnType.Number]
+    ["page", ColumnType.Number], ["curPage", ColumnType.Number], ["zIndex", ColumnType.Number]
 ]);
 
 @observer
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 571967743..24bd24d11 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -127,19 +127,19 @@ class TreeView extends React.Component<TreeViewProps> {
 
     onPointerDown = (e: React.PointerEvent) => e.stopPropagation();
     onPointerEnter = (e: React.PointerEvent): void => {
-        this.props.active() && (this.props.document.libraryBrush = true);
+        this.props.active() && Doc.BrushDoc(this.dataDoc);
         if (e.buttons === 1 && SelectionManager.GetIsDragging()) {
             this._header!.current!.className = "treeViewItem-header";
             document.addEventListener("pointermove", this.onDragMove, true);
         }
     }
     onPointerLeave = (e: React.PointerEvent): void => {
-        this.props.document.libraryBrush = false;
+        Doc.UnBrushDoc(this.dataDoc);
         this._header!.current!.className = "treeViewItem-header";
         document.removeEventListener("pointermove", this.onDragMove, true);
     }
     onDragMove = (e: PointerEvent): void => {
-        this.props.document.libraryBrush = false;
+        Doc.UnBrushDoc(this.dataDoc);
         let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY);
         let rect = this._header!.current!.getBoundingClientRect();
         let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2);
@@ -359,7 +359,7 @@ class TreeView extends React.Component<TreeViewProps> {
         return <>
             <div className="docContainer" id={`docContainer-${this.props.parentKey}`} ref={reference} onPointerDown={onItemDown}
                 style={{
-                    background: BoolCast(this.props.document.libraryBrush) ? "#06121212" : "0",
+                    background: Doc.IsBrushed(this.props.document) ? "#06121212" : "0",
                     outline: BoolCast(this.props.document.workspaceBrush) ? "dashed 1px #06123232" : undefined,
                     pointerEvents: this.props.active() || SelectionManager.GetIsDragging() ? "all" : "none"
                 }} >
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index a7b4f33db..e911dc47c 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -303,7 +303,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             fullScreenAlias.showCaption = true;
             this.props.addDocTab(fullScreenAlias, this.dataDoc, "inTab");
             SelectionManager.DeselectAll();
-            this.props.Document.libraryBrush = false;
+            Doc.UnBrushDoc(this.props.Document);
         }
         else if (CurrentUserUtils.MainDocId !== this.props.Document[Id] &&
             (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
@@ -445,13 +445,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             targetDoc.targetContext = de.data.targetContext;
             let annotations = await DocListCastAsync(annotationDoc.annotations);
             if (annotations) {
-                annotations.forEach(anno => {
-                    anno.target = targetDoc;
-                });
+                annotations.forEach(anno => anno.target = targetDoc);
             }
-            let pdfDoc = await Cast(annotationDoc.pdfDoc, Doc);
-            if (pdfDoc) {
-                DocUtils.MakeLink(annotationDoc, targetDoc, this.props.ContainingCollectionView!.props.Document, `Annotation from ${StrCast(pdfDoc.title)}`, "", StrCast(pdfDoc.title));
+            let annotDoc = await Cast(annotationDoc.annotationOn, Doc);
+            if (annotDoc) {
+                DocUtils.MakeLink(annotationDoc, targetDoc, this.props.ContainingCollectionView!.props.Document, `Annotation from ${StrCast(annotDoc.title)}`, "", StrCast(annotDoc.title));
             }
         }
         if (de.data instanceof DragManager.LinkDragData) {
@@ -647,8 +645,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         });
     }
 
-    onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; };
-    onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; };
+    onPointerEnter = (e: React.PointerEvent): void => { Doc.BrushDoc(this.props.Document); };
+    onPointerLeave = (e: React.PointerEvent): void => { Doc.UnBrushDoc(this.props.Document); };
 
     isSelected = () => SelectionManager.IsSelected(this);
     @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); };
@@ -695,22 +693,23 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             });
         }
         let showTextTitle = showTitle && StrCast(this.layoutDoc.layout).startsWith("<FormattedTextBox") ? showTitle : undefined;
+        let brushDegree = Doc.IsBrushedDegree(this.layoutDoc);
         return (
             <div className={`documentView-node${this.topMost ? "-topmost" : ""}`}
                 ref={this._mainCont}
                 style={{
                     pointerEvents: this.layoutDoc.isBackground && !this.isSelected() ? "none" : "all",
                     color: foregroundColor,
-                    outlineColor: "maroon",
-                    outlineStyle: "dashed",
-                    outlineWidth: BoolCast(this.layoutDoc.libraryBrush) && !StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
-                        `${this.props.ScreenToLocalTransform().Scale}px` : "0px",
-                    marginLeft: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
-                        `${-1 * this.props.ScreenToLocalTransform().Scale}px` : undefined,
-                    marginTop: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
-                        `${-1 * this.props.ScreenToLocalTransform().Scale}px` : undefined,
-                    border: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
-                        `dashed maroon ${this.props.ScreenToLocalTransform().Scale}px` : undefined,
+                    outlineColor: ["transparent", "maroon", "maroon"][brushDegree],
+                    outlineStyle: ["none", "dashed", "solid"][brushDegree],
+                    outlineWidth: brushDegree && !StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
+                        `${brushDegree * this.props.ScreenToLocalTransform().Scale}px` : "0px",
+                    marginLeft: brushDegree && StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
+                        `${-brushDegree * this.props.ScreenToLocalTransform().Scale}px` : undefined,
+                    marginTop: brushDegree && StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
+                        `${-brushDegree * this.props.ScreenToLocalTransform().Scale}px` : undefined,
+                    border: brushDegree && StrCast(Doc.GetProto(this.props.Document).borderRounding) ?
+                        `${["none", "dashed", "solid"][brushDegree]} ${["transparent", "maroon", "maroon"][brushDegree]} ${this.props.ScreenToLocalTransform().Scale}px` : undefined,
                     borderRadius: "inherit",
                     background: backgroundColor,
                     width: nativeWidth,
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 9dd0643df..44b5d2c21 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -674,7 +674,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                 style={{
                     height: this.props.height ? this.props.height : undefined,
                     background: this.props.hideOnLeave ? "rgba(0,0,0,0.4)" : undefined,
-                    opacity: this.props.hideOnLeave ? (this._entered || this.props.isSelected() || this.props.Document.libraryBrush ? 1 : 0.1) : 1,
+                    opacity: this.props.hideOnLeave ? (this._entered || this.props.isSelected() || Doc.IsBrushed(this.props.Document) ? 1 : 0.1) : 1,
                     color: this.props.color ? this.props.color : this.props.hideOnLeave ? "white" : "inherit",
                     pointerEvents: interactive,
                     fontSize: "13px"
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 95df10c58..7cd62f4e0 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -184,7 +184,7 @@ export class PDFViewer extends React.Component<IViewerProps> {
             annoDoc.color = color;
             annoDoc.type = AnnotationTypes.Region;
             annoDocs.push(annoDoc);
-            annoDoc.isBackground = true;
+            annoDoc.isButton = true;
             anno.remove();
             this.props.addDocument && this.props.addDocument(annoDoc, false);
             mainAnnoDoc = annoDoc;
@@ -208,7 +208,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
             mainAnnoDocProto.y = Math.max(minY, 0);
             mainAnnoDocProto.annotations = new List<Doc>(annoDocs);
         }
-        mainAnnoDocProto.pdfDoc = this.props.Document;
         mainAnnoDocProto.title = "Annotation on " + StrCast(this.props.Document.title);
         mainAnnoDocProto.annotationOn = this.props.Document;
         if (sourceDoc && createLink) {
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index 4986f44d5..6bd98cbaa 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -112,8 +112,8 @@ export default class Page extends React.Component<IPageProps> {
                         if (!BoolCast(annotationDoc.linkedToDoc)) {
                             let annotations = await DocListCastAsync(annotationDoc.annotations);
                             annotations && annotations.forEach(anno => anno.target = targetDoc);
-                            let pdfDoc = await Cast(annotationDoc.pdfDoc, Doc);
-                            pdfDoc && DocUtils.MakeLink(annotationDoc, targetDoc, dragData.targetContext, `Annotation from ${StrCast(pdfDoc.title)}`, "", StrCast(pdfDoc.title))
+                            let parentDoc = await Cast(annotationDoc.annotationOn, Doc);
+                            parentDoc && DocUtils.MakeLink(annotationDoc, targetDoc, dragData.targetContext, `Annotation from ${StrCast(parentDoc.title)}`, "", StrCast(parentDoc.title))
                         }
                     }
                 },
@@ -144,10 +144,7 @@ export default class Page extends React.Component<IPageProps> {
     onPointerDown = (e: React.PointerEvent): void => {
         // if alt+left click, drag and annotate
         if (NumCast(this.props.Document.scale, 1) !== 1) return;
-        if (e.altKey && e.button === 0) {
-            e.stopPropagation();
-        }
-        else if (e.button === 0) {
+        if (!e.altKey && e.button === 0) {
             PDFMenu.Instance.StartDrag = this.startDrag;
             PDFMenu.Instance.Highlight = this.highlight;
             PDFMenu.Instance.Snippet = this.createSnippet;
diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx
index e2d8daea9..d98b66324 100644
--- a/src/client/views/presentationview/PresentationElement.tsx
+++ b/src/client/views/presentationview/PresentationElement.tsx
@@ -706,7 +706,7 @@ export default class PresentationElement extends React.Component<PresentationEle
      * It makes it possible to show dropping lines on drop targets.
      */
     onDragMove = (e: PointerEvent): void => {
-        this.props.document.libraryBrush = false;
+        Doc.UnBrushDoc(this.props.document);
         let x = this.ScreenToLocalListTransform(e.clientX, e.clientY);
         let rect = this.header!.getBoundingClientRect();
         let bounds = this.ScreenToLocalListTransform(rect.left, rect.top + rect.height / 2);
@@ -889,7 +889,7 @@ export default class PresentationElement extends React.Component<PresentationEle
                 style={{
                     outlineColor: "maroon",
                     outlineStyle: "dashed",
-                    outlineWidth: BoolCast(p.document.libraryBrush) ? `1px` : "0px",
+                    outlineWidth: Doc.IsBrushed(p.document) ? `1px` : "0px",
                 }}
                 onClick={e => { p.gotoDocument(p.index, NumCast(this.props.mainDocument.selectedDoc)); e.stopPropagation(); }}>
                 <strong className="presentationView-name">
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index c4af30f5c..8201aa374 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -105,23 +105,11 @@ export interface LinkMenuProps {
 @observer
 export class LinkContextMenu extends React.Component<LinkMenuProps> {
 
-    highlightDoc = (doc: Doc) => {
-        return () => {
-            doc.libraryBrush = true;
-        };
-    }
+    highlightDoc = (doc: Doc) => () => Doc.BrushDoc(doc);
 
-    unHighlightDoc = (doc: Doc) => {
-        return () => {
-            doc.libraryBrush = false;
-        };
-    }
+    unHighlightDoc = (doc: Doc) => () => Doc.UnBrushDoc(doc);
 
-    getOnClick(col: Doc) {
-        return () => {
-            CollectionDockingView.Instance.AddRightSplit(col, undefined);
-        };
-    }
+    getOnClick = (col: Doc) => () => CollectionDockingView.Instance.AddRightSplit(col, undefined);
 
     render() {
         return (
@@ -286,14 +274,12 @@ export class SearchItem extends React.Component<SearchItemProps> {
 
                 let doc1 = Cast(this.props.doc.anchor1, Doc, null);
                 let doc2 = Cast(this.props.doc.anchor2, Doc, null);
-                doc1 && (doc1.libraryBrush = true);
-                doc2 && (doc2.libraryBrush = true);
+                Doc.BrushDoc(doc1);
+                Doc.BrushDoc(doc2);
             }
         } else {
-            let docViews: DocumentView[] = DocumentManager.Instance.getAllDocumentViews(this.props.doc);
-            docViews.forEach(element => {
-                element.props.Document.libraryBrush = true;
-            });
+            DocumentManager.Instance.getAllDocumentViews(this.props.doc).forEach(element =>
+                Doc.BrushDoc(element.props.Document));
         }
     }
 
@@ -303,14 +289,12 @@ export class SearchItem extends React.Component<SearchItemProps> {
 
                 let doc1 = Cast(this.props.doc.anchor1, Doc, null);
                 let doc2 = Cast(this.props.doc.anchor2, Doc, null);
-                doc1 && (doc1.libraryBrush = false);
-                doc2 && (doc2.libraryBrush = false);
+                Doc.UnBrushDoc(doc1);
+                Doc.UnBrushDoc(doc2);
             }
         } else {
-            let docViews: DocumentView[] = DocumentManager.Instance.getAllDocumentViews(this.props.doc);
-            docViews.forEach(element => {
-                element.props.Document.libraryBrush = false;
-            });
+            DocumentManager.Instance.getAllDocumentViews(this.props.doc).
+                forEach(element => Doc.UnBrushDoc(element.props.Document));
         }
     }
 
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index c01f4e8cf..b3d1dc109 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -542,4 +542,22 @@ export namespace Doc {
             }
         });
     }
+
+    export class DocBrush {
+        @observable BrushedDoc: Doc[] = [];
+    }
+    const manager = new DocBrush();
+    export function IsBrushed(doc: Doc) {
+        return manager.BrushedDoc.some(d => Doc.AreProtosEqual(d, doc));
+    }
+    export function IsBrushedDegree(doc: Doc) {
+        return manager.BrushedDoc.some(d => d === doc) ? 2 : Doc.IsBrushed(doc) ? 1 : 0;
+    }
+    export function BrushDoc(doc: Doc) {
+        if (manager.BrushedDoc.indexOf(doc) === -1) runInAction(() => manager.BrushedDoc.push(doc));
+    }
+    export function UnBrushDoc(doc: Doc) {
+        let index = manager.BrushedDoc.indexOf(doc);
+        if (index !== -1) runInAction(() => manager.BrushedDoc.splice(index, 1));
+    }
 }
\ No newline at end of file
diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts
index c6f693f7f..48ae9f216 100644
--- a/src/new_fields/util.ts
+++ b/src/new_fields/util.ts
@@ -6,7 +6,6 @@ import { RefField } from "./RefField";
 import { ObjectField } from "./ObjectField";
 import { action } from "mobx";
 import { Parent, OnUpdate, Update, Id, SelfProxy, Self } from "./FieldSymbols";
-import { ComputedField } from "./ScriptField";
 
 function _readOnlySetter(): never {
     throw new Error("Documents can't be modified in read-only mode");
diff --git a/src/scraping/buxton/scraper.py b/src/scraping/buxton/scraper.py
index f0f45d8f9..29cb8a256 100644
--- a/src/scraping/buxton/scraper.py
+++ b/src/scraping/buxton/scraper.py
@@ -88,8 +88,7 @@ def write_schema(parse_results, display_fields, storage_key):
             "panX": 0,
             "panY": 0,
             "zoomBasis": 1,
-            "zIndex": 2,
-            "libraryBrush": False,
+            "zIndex": 2
             "viewType": 2
         },
         "__type": "Doc"
@@ -130,8 +129,7 @@ def write_text_doc(content):
             "x": 10,
             "y": 10,
             "width": 400,
-            "zIndex": 2,
-            "libraryBrush": False
+            "zIndex": 2
         },
         "__type": "Doc"
     }
@@ -183,8 +181,7 @@ def write_image(folder, name):
             "x": 10,
             "y": 10,
             "width": min(800, native_width),
-            "zIndex": 2,
-            "libraryBrush": False
+            "zIndex": 2
         },
         "__type": "Doc"
     }
-- 
cgit v1.2.3-70-g09d2


From 4b358bfc1122f91b907305c15fc4214d7fc74a4c Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Fri, 9 Aug 2019 15:01:42 -0400
Subject: Compile errors and Fixed read only modes

---
 src/client/DocServer.ts                            | 11 ++++---
 src/client/views/MainView.tsx                      | 17 +++++-----
 .../views/collections/CollectionSchemaView.tsx     |  4 +--
 src/new_fields/Doc.ts                              | 35 +++++++++++---------
 src/new_fields/util.ts                             | 38 +++++++++++++---------
 5 files changed, 59 insertions(+), 46 deletions(-)

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

diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index 977eb7772..bf5168c22 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -27,9 +27,10 @@ export namespace DocServer {
     // indicates whether or not a document is currently being udpated, and, if so, its id
 
     export enum WriteMode {
-        Always = 0,
-        None = 1,
-        SameUser = 2,
+        Default = 0, //Anything goes
+        Playground = 1,
+        LiveReadonly = 2,
+        LivePlayground = 3,
     }
 
     const fieldWriteModes: { [field: string]: WriteMode } = {};
@@ -37,7 +38,7 @@ export namespace DocServer {
 
     export function setFieldWriteMode(field: string, writeMode: WriteMode) {
         fieldWriteModes[field] = writeMode;
-        if (writeMode === WriteMode.Always) {
+        if (writeMode !== WriteMode.Playground) {
             const docs = docsWithUpdates[field];
             if (docs) {
                 docs.forEach(doc => Doc.RunCachedUpdate(doc, field));
@@ -47,7 +48,7 @@ export namespace DocServer {
     }
 
     export function getFieldWriteMode(field: string) {
-        return fieldWriteModes[field];
+        return fieldWriteModes[field] || WriteMode.Default;
     }
 
     export function registerDocWithCachedUpdate(doc: Doc, field: string, oldValue: any) {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 7629a0906..eabb23489 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -435,7 +435,6 @@ export class MainView extends React.Component {
     }
 
 
-    private mode: DocServer.WriteMode = DocServer.WriteMode.Always;
     @observable private _colorPickerDisplay = false;
     /* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */
     nodesMenu() {
@@ -463,6 +462,11 @@ export class MainView extends React.Component {
         ];
         if (!ClientUtils.RELEASE) btns.unshift([React.createRef<HTMLDivElement>(), "cat", "Add Cat Image", addImageNode]);
 
+        const setWriteMode = (mode: DocServer.WriteMode) => {
+            console.log(DocServer.WriteMode[mode]);
+            DocServer.setFieldWriteMode("x", mode);
+            DocServer.setFieldWriteMode("y", mode);
+        };
         return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 20, bottom: 20 }} >
             <input type="checkbox" id="add-menu-toggle" ref={this.addMenuToggle} />
             <label htmlFor="add-menu-toggle" style={{ marginTop: 2 }} title="Add Node"><p>+</p></label>
@@ -480,13 +484,10 @@ export class MainView extends React.Component {
                             </button>
                         </div></li>)}
                     <li key="undoTest"><button className="add-button round-button" title="Click if undo isn't working" onClick={() => UndoManager.TraceOpenBatches()}><FontAwesomeIcon icon="exclamation" size="sm" /></button></li>
-                    <li key="test"><button className="add-button round-button" title="asdf" onClick={() => {
-                        this.mode++;
-                        this.mode = this.mode % 3;
-                        console.log(DocServer.WriteMode[this.mode]);
-                        DocServer.setFieldWriteMode("x", this.mode);
-                        DocServer.setFieldWriteMode("y", this.mode);
-                    }}><FontAwesomeIcon icon="exclamation" size="sm" /></button></li>
+                    <li key="test"><button className="add-button round-button" title="Default" onClick={() => setWriteMode(DocServer.WriteMode.Default)}><FontAwesomeIcon icon="exclamation" size="sm" /></button></li>
+                    <li key="test1"><button className="add-button round-button" title="Playground" onClick={() => setWriteMode(DocServer.WriteMode.Playground)}><FontAwesomeIcon icon="exclamation" size="sm" /></button></li>
+                    <li key="test2"><button className="add-button round-button" title="Live Playground" onClick={() => setWriteMode(DocServer.WriteMode.LivePlayground)}><FontAwesomeIcon icon="exclamation" size="sm" /></button></li>
+                    <li key="test3"><button className="add-button round-button" title="Live Readonly" onClick={() => setWriteMode(DocServer.WriteMode.LiveReadonly)}><FontAwesomeIcon icon="exclamation" size="sm" /></button></li>
                     <li key="color"><button className="add-button round-button" title="Select Color" style={{ zIndex: 1000 }} onClick={() => this.toggleColorPicker()}><div className="toolbar-color-button" style={{ backgroundColor: InkingControl.Instance.selectedColor }} >
                         <div className="toolbar-color-picker" onClick={this.onColorClick} style={this._colorPickerDisplay ? { color: "black", display: "block" } : { color: "black", display: "none" }}>
                             <SketchPicker color={InkingControl.Instance.selectedColor} onChange={InkingControl.Instance.switchColor} />
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index ebfa737be..897796174 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -303,13 +303,13 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
             return resized;
         }, [] as { "id": string, "value": number }[]);
     }
-    @computed get sorted(): { "id": string, "desc"?: true }[] {
+    @computed get sorted(): { id: string, desc: boolean }[] {
         return this.columns.reduce((sorted, shf) => {
             if (shf.desc) {
                 sorted.push({ "id": shf.heading, "desc": shf.desc });
             }
             return sorted;
-        }, [] as { "id": string, "desc"?: true }[]);
+        }, [] as { id: string, desc: boolean }[]);
     }
 
     @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); }
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 87e048140..543ee46cc 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -13,6 +13,7 @@ import { List } from "./List";
 import { DocumentType } from "../client/documents/Documents";
 import { ComputedField, ScriptField } from "./ScriptField";
 import { PrefetchProxy, ProxyField } from "./Proxy";
+import { CurrentUserUtils } from "../server/authentication/models/current_user_utils";
 
 export namespace Field {
     export function toKeyValueString(doc: Doc, key: string): string {
@@ -68,6 +69,7 @@ export function DocListCast(field: FieldResult): Doc[] {
 
 export const WidthSym = Symbol("Width");
 export const HeightSym = Symbol("Height");
+export const UpdatingFromServer = Symbol("UpdatingFromServer");
 const CachedUpdates = Symbol("Cached updates");
 
 function fetchProto(doc: Doc) {
@@ -77,8 +79,6 @@ function fetchProto(doc: Doc) {
     }
 }
 
-let updatingFromServer = false;
-
 @scriptingGlobal
 @Deserializable("Doc", fetchProto).withFields(["id"])
 export class Doc extends RefField {
@@ -132,8 +132,10 @@ export class Doc extends RefField {
     //{ [key: string]: Field | FieldWaiting | undefined }
     private ___fields: any = {};
 
+    private [UpdatingFromServer]: boolean = false;
+
     private [Update] = (diff: any) => {
-        if (updatingFromServer) {
+        if (this[UpdatingFromServer]) {
             return;
         }
         DocServer.UpdateField(this[Id], diff);
@@ -152,6 +154,7 @@ export class Doc extends RefField {
 
     public async [HandleUpdate](diff: any) {
         const set = diff.$set;
+        const sameAuthor = this.author === CurrentUserUtils.email;
         if (set) {
             for (const key in set) {
                 if (!key.startsWith("fields.")) {
@@ -160,14 +163,15 @@ export class Doc extends RefField {
                 const fKey = key.substring(7);
                 const fn = async () => {
                     const value = await SerializationHelper.Deserialize(set[key]);
-                    updatingFromServer = true;
+                    this[UpdatingFromServer] = true;
                     this[fKey] = value;
-                    updatingFromServer = false;
+                    this[UpdatingFromServer] = false;
                 };
-                if (DocServer.getFieldWriteMode(fKey)) {
-                    this[CachedUpdates][fKey] = fn;
-                } else {
+                if (sameAuthor || DocServer.getFieldWriteMode(fKey) !== DocServer.WriteMode.Playground) {
+                    delete this[CachedUpdates][fKey];
                     await fn();
+                } else {
+                    this[CachedUpdates][fKey] = fn;
                 }
             }
         }
@@ -179,14 +183,15 @@ export class Doc extends RefField {
                 }
                 const fKey = key.substring(7);
                 const fn = () => {
-                    updatingFromServer = true;
+                    this[UpdatingFromServer] = true;
                     delete this[fKey];
-                    updatingFromServer = false;
+                    this[UpdatingFromServer] = false;
                 };
-                if (DocServer.getFieldWriteMode(fKey)) {
-                    this[CachedUpdates][fKey] = fn;
-                } else {
+                if (sameAuthor || DocServer.getFieldWriteMode(fKey) !== DocServer.WriteMode.Playground) {
+                    delete this[CachedUpdates][fKey];
                     await fn();
+                } else {
+                    this[CachedUpdates][fKey] = fn;
                 }
             }
         }
@@ -214,9 +219,9 @@ export namespace Doc {
     export function AddCachedUpdate(doc: Doc, field: string, oldValue: any) {
         const val = oldValue;
         doc[CachedUpdates][field] = () => {
-            updatingFromServer = true;
+            doc[UpdatingFromServer] = true;
             doc[field] = val;
-            updatingFromServer = false;
+            doc[UpdatingFromServer] = false;
         };
     }
     export function MakeReadOnly(): { end(): void } {
diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts
index 6c05da507..c546e2aac 100644
--- a/src/new_fields/util.ts
+++ b/src/new_fields/util.ts
@@ -1,5 +1,5 @@
 import { UndoManager } from "../client/util/UndoManager";
-import { Doc, Field, FieldResult } from "./Doc";
+import { Doc, Field, FieldResult, UpdatingFromServer } from "./Doc";
 import { SerializationHelper } from "../client/util/SerializationHelper";
 import { ProxyField } from "./Proxy";
 import { RefField } from "./RefField";
@@ -59,23 +59,29 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number
         delete curValue[Parent];
         delete curValue[OnUpdate];
     }
-    if (value === undefined) {
-        delete target.__fields[prop];
-    } else {
-        target.__fields[prop] = value;
-    }
     const writeMode = DocServer.getFieldWriteMode(prop as string);
-    if (typeof value === "object" && !(value instanceof ObjectField)) debugger;
-    if (!writeMode || (writeMode === DocServer.WriteMode.SameUser && receiver.author === CurrentUserUtils.email)) {
-        if (value === undefined) target[Update]({ '$unset': { ["fields." + prop]: "" } });
-        else target[Update]({ '$set': { ["fields." + prop]: value instanceof ObjectField ? SerializationHelper.Serialize(value) : (value === undefined ? null : value) } });
-    } else {
-        DocServer.registerDocWithCachedUpdate(receiver, prop as string, curValue);
+    const fromServer = target[UpdatingFromServer];
+    const sameAuthor = fromServer || (receiver.author === CurrentUserUtils.email);
+    const writeToDoc = sameAuthor || (writeMode !== DocServer.WriteMode.LiveReadonly);
+    const writeToServer = sameAuthor || (writeMode === DocServer.WriteMode.Default);
+    if (writeToDoc) {
+        if (value === undefined) {
+            delete target.__fields[prop];
+        } else {
+            target.__fields[prop] = value;
+        }
+        if (typeof value === "object" && !(value instanceof ObjectField)) debugger;
+        if (writeToServer) {
+            if (value === undefined) target[Update]({ '$unset': { ["fields." + prop]: "" } });
+            else target[Update]({ '$set': { ["fields." + prop]: value instanceof ObjectField ? SerializationHelper.Serialize(value) : (value === undefined ? null : value) } });
+        } else {
+            DocServer.registerDocWithCachedUpdate(receiver, prop as string, curValue);
+        }
+        UndoManager.AddEvent({
+            redo: () => receiver[prop] = value,
+            undo: () => receiver[prop] = curValue
+        });
     }
-    UndoManager.AddEvent({
-        redo: () => receiver[prop] = value,
-        undo: () => receiver[prop] = curValue
-    });
     return true;
 });
 
-- 
cgit v1.2.3-70-g09d2


From e291730c407932506a80f96457a84dce1820521d Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 9 Aug 2019 17:42:11 -0400
Subject: made onClick a prop

---
 src/client/views/MainOverlayTextBox.tsx                  |  1 +
 src/client/views/MainView.tsx                            |  2 ++
 src/client/views/collections/CollectionSchemaView.tsx    | 16 +++++++++-------
 src/client/views/collections/CollectionStackingView.tsx  |  1 +
 src/client/views/collections/CollectionView.tsx          |  4 ++++
 .../collectionFreeForm/CollectionFreeFormView.tsx        |  8 ++++++--
 src/client/views/nodes/DocumentContentsView.tsx          | 13 +++++++++++--
 src/client/views/nodes/DocumentView.tsx                  | 16 +++++++++-------
 src/client/views/nodes/FieldView.tsx                     |  3 ++-
 9 files changed, 45 insertions(+), 19 deletions(-)

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

diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index fccbeb16c..0f20dc3a8 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -142,6 +142,7 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
                             <FormattedTextBox color={`${this._textColor}`} fieldKey={this.TextFieldKey} fieldExt="" hideOnLeave={this._textHideOnLeave} isOverlay={true}
                                 Document={FormattedTextBox.InputBoxOverlay.props.Document}
                                 DataDoc={FormattedTextBox.InputBoxOverlay.props.DataDoc}
+                                onClick={emptyFunction}
                                 isSelected={returnTrue} select={emptyFunction} renderDepth={0} selectOnLoad={true}
                                 ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue} ContentScaling={returnOne}
                                 ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyFunction} addDocTab={this.addDocTab} />
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 0d8ade247..bb0048982 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -321,6 +321,7 @@ export class MainView extends React.Component {
                             DataDoc={undefined}
                             addDocument={undefined}
                             addDocTab={emptyFunction}
+                            onClick={emptyFunction}
                             removeDocument={undefined}
                             ScreenToLocalTransform={Transform.Identity}
                             ContentScaling={returnOne}
@@ -385,6 +386,7 @@ export class MainView extends React.Component {
             addDocument={undefined}
             addDocTab={this.addDocTabFunc}
             removeDocument={undefined}
+            onClick={emptyFunction}
             ScreenToLocalTransform={Transform.Identity}
             ContentScaling={returnOne}
             PanelWidth={this.flyoutWidthFunc}
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index ebfa737be..67b8b4a8d 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -30,7 +30,7 @@ import { undoBatch } from "../../util/UndoManager";
 import { CollectionSchemaHeader, CollectionSchemaAddColumnHeader } from "./CollectionSchemaHeaders";
 import { CellProps, CollectionSchemaCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaBooleanCell, CollectionSchemaCheckboxCell, CollectionSchemaDocCell } from "./CollectionSchemaCells";
 import { MovableColumn, MovableRow } from "./CollectionSchemaMovableTableHOC";
-import { ComputedField } from "../../../new_fields/ScriptField";
+import { ComputedField, ScriptField } from "../../../new_fields/ScriptField";
 import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
 
 
@@ -899,6 +899,7 @@ interface CollectionSchemaPreviewProps {
     height: () => number;
     showOverlays?: (doc: Doc) => { title?: string, caption?: string };
     CollectionView?: CollectionView | CollectionPDFView | CollectionVideoView;
+    onClick?: () => void | ScriptField;
     getTransform: () => Transform;
     addDocument: (document: Doc, allowDuplicates?: boolean) => boolean;
     moveDocument: (document: Doc, target: Doc, addDoc: ((doc: Doc) => boolean)) => boolean;
@@ -988,23 +989,24 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
                         DataDoc={this.props.DataDocument}
                         Document={this.props.Document}
                         fitToBox={this.props.fitToBox}
-                        renderDepth={this.props.renderDepth + 1}
-                        selectOnLoad={false}
+                        onClick={this.props.onClick}
                         showOverlays={this.props.showOverlays}
                         addDocument={this.props.addDocument}
                         removeDocument={this.props.removeDocument}
                         moveDocument={this.props.moveDocument}
+                        whenActiveChanged={this.props.whenActiveChanged}
+                        ContainingCollectionView={this.props.CollectionView}
+                        addDocTab={this.props.addDocTab}
+                        parentActive={this.props.active}
                         ScreenToLocalTransform={this.getTransform}
+                        renderDepth={this.props.renderDepth + 1}
+                        selectOnLoad={false}
                         ContentScaling={this.contentScaling}
                         PanelWidth={this.PanelWidth}
                         PanelHeight={this.PanelHeight}
-                        ContainingCollectionView={this.props.CollectionView}
                         focus={emptyFunction}
                         backgroundColor={returnEmptyString}
-                        parentActive={this.props.active}
-                        whenActiveChanged={this.props.whenActiveChanged}
                         bringToFront={emptyFunction}
-                        addDocTab={this.props.addDocTab}
                         zoomToScale={emptyFunction}
                         getScale={returnOne}
                     />
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 112d64e3d..22af98c4d 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -121,6 +121,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
             showOverlays={this.overlays}
             renderDepth={this.props.renderDepth}
             fitToBox={this.props.fitToBox}
+            onClick={this.props.onClick}
             width={width}
             height={height}
             getTransform={finalDxf}
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 7a402798e..8b939259c 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -30,6 +30,10 @@ export class CollectionView extends React.Component<FieldViewProps> {
 
     public static LayoutString(fieldStr: string = "data", fieldExt: string = "") { return FieldView.LayoutString(CollectionView, fieldStr, fieldExt); }
 
+    constructor(props:any) {
+        super(props);
+    }
+
     componentDidMount = () => {
         this._reactionDisposer = reaction(() => StrCast(this.props.Document.chromeStatus),
             () => {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index ba8dcff98..30010e826 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -37,8 +37,6 @@ import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
 import { DocumentType, Docs } from "../../../documents/Documents";
-import { RouteStore } from "../../../../server/RouteStore";
-import { string, number, elementType } from "prop-types";
 
 library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard);
 
@@ -195,6 +193,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     private get _pheight() { return this.props.PanelHeight(); }
     private inkKey = "ink";
 
+    constructor(props: any) {
+        super(props);
+    }
+
     get parentScaling() {
         return (this.props as any).ContentScaling && this.fitToBox && !this.isAnnotationOverlay ? (this.props as any).ContentScaling() : 1;
     }
@@ -631,6 +633,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             addDocument: this.props.addDocument,
             removeDocument: this.props.removeDocument,
             moveDocument: this.props.moveDocument,
+            onClick: this.props.onClick,
             ScreenToLocalTransform: pair.layout.z ? this.getTransformOverlay : this.getTransform,
             renderDepth: this.props.renderDepth + 1,
             selectOnLoad: pair.layout[Id] === this._selectOnLoaded,
@@ -655,6 +658,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             addDocument: this.props.addDocument,
             removeDocument: this.props.removeDocument,
             moveDocument: this.props.moveDocument,
+            onClick: this.props.onClick,
             ScreenToLocalTransform: this.getTransform,
             renderDepth: this.props.renderDepth,
             selectOnLoad: layoutDoc[Id] === this._selectOnLoaded,
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 6b7b239f0..2466f13f6 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -28,7 +28,7 @@ import { Cast, StrCast, NumCast } from "../../../new_fields/Types";
 import { List } from "../../../new_fields/List";
 import { Doc } from "../../../new_fields/Doc";
 import DirectoryImportBox from "../../util/Import & Export/DirectoryImportBox";
-import { CollectionViewType } from "../collections/CollectionBaseView";
+import { ScriptField } from "../../../new_fields/ScriptField";
 const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
 
 type BindingProps = Without<FieldViewProps, 'fieldKey'>;
@@ -49,6 +49,7 @@ const ObserverJsxParser: typeof JsxParser = ObserverJsxParser1 as any;
 export class DocumentContentsView extends React.Component<DocumentViewProps & {
     isSelected: () => boolean,
     select: (ctrl: boolean) => void,
+    onClick?: ScriptField,
     layoutKey: string,
     hideOnLeave?: boolean
 }> {
@@ -81,7 +82,13 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
     }
 
     CreateBindings(): JsxBindings {
-        return { props: { ...OmitKeys(this.props, ['parentActive'], (obj: any) => obj.active = this.props.parentActive).omit, Document: this.layoutDoc, DataDoc: this.dataDoc } };
+        let list = {
+            ...OmitKeys(this.props, ['parentActive'], (obj: any) => obj.active = this.props.parentActive).omit,
+            Document: this.layoutDoc,
+            DataDoc: this.dataDoc,
+            onClick: this.props.onClick
+        };
+        return { props: list };
     }
 
     @computed get templates(): List<string> {
@@ -100,10 +107,12 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
         if (this.props.renderDepth > 7) return (null);
         if (!this.layout && (this.props.layoutKey !== "overlayLayout" || !this.templates.length)) return (null);
         return <ObserverJsxParser
+            blacklistedAttrs={[]}
             components={{ FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, DragBox, ButtonBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox, YoutubeBox }}
             bindings={this.CreateBindings()}
             jsx={this.finalLayout}
             showWarnings={true}
+
             onError={(test: any) => { console.log(test); }}
         />;
     }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index cf16db203..b8e2eb436 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -39,7 +39,6 @@ import { FormattedTextBox } from './FormattedTextBox';
 import React = require("react");
 import { DictationManager } from '../../util/DictationManager';
 import { MainView } from '../MainView';
-import requestPromise = require('request-promise');
 import { ScriptBox } from '../ScriptBox';
 import { CompileScript } from '../../util/Scripting';
 import { DocumentIconContainer } from './DocumentIcon';
@@ -84,6 +83,7 @@ export interface DocumentViewProps {
     Document: Doc;
     DataDoc?: Doc;
     fitToBox?: boolean;
+    onClick?: ScriptField;
     addDocument?: (doc: Doc, allowDuplicates?: boolean) => boolean;
     removeDocument?: (doc: Doc) => boolean;
     moveDocument?: (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean;
@@ -297,8 +297,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     onClick = async (e: React.MouseEvent) => {
         if (e.nativeEvent.cancelBubble) return; // needed because EditableView may stopPropagation which won't apparently stop this event from firing.
         e.stopPropagation();
-        if (this.Document.onClick) {
-            this.Document.onClick.script.run({ this: this.props.Document });
+        if (this.onClickHandler) {
+            this.onClickHandler.script.run({ this: this.props.Document });
             e.preventDefault();
             return;
         }
@@ -687,14 +687,16 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
     onPointerLeave = (e: React.PointerEvent): void => { Doc.UnBrushDoc(this.props.Document); };
 
     isSelected = () => SelectionManager.IsSelected(this);
-    @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); };
-
+    @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); }
     @computed get nativeWidth() { return this.Document.nativeWidth || 0; }
     @computed get nativeHeight() { return this.Document.nativeHeight || 0; }
+    @computed get onClickHandler() { return this.props.onClick ? this.props.onClick : this.Document.onClick; }
     @computed get contents() {
         return (<DocumentContentsView {...this.props}
             ChromeHeight={this.chromeHeight}
-            isSelected={this.isSelected} select={this.select}
+            isSelected={this.isSelected}
+            select={this.select}
+            onClick={this.onClickHandler}
             selectOnLoad={this.props.selectOnLoad}
             layoutKey={"layout"}
             fitToBox={BoolCast(this.props.Document.fitToBox) ? true : this.props.fitToBox}
@@ -783,7 +785,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                         }
                         {!showCaption ? (null) :
                             <div style={{ position: "absolute", bottom: 0, transformOrigin: "bottom left", width: `${100 * this.props.ContentScaling()}%`, transform: `scale(${1 / this.props.ContentScaling()})` }}>
-                                <FormattedTextBox {...this.props} DataDoc={this.dataDoc} active={returnTrue} isSelected={this.isSelected} focus={emptyFunction} select={this.select} selectOnLoad={this.props.selectOnLoad} fieldExt={""} hideOnLeave={true} fieldKey={showCaption} />
+                                <FormattedTextBox {...this.props} onClick={this.onClickHandler} DataDoc={this.dataDoc} active={returnTrue} isSelected={this.isSelected} focus={emptyFunction} select={this.select} selectOnLoad={this.props.selectOnLoad} fieldExt={""} hideOnLeave={true} fieldKey={showCaption} />
                             </div>
                         }
                     </div>
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index da54ecc3a..3287949e2 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -17,7 +17,7 @@ import { IconBox } from "./IconBox";
 import { ImageBox } from "./ImageBox";
 import { PDFBox } from "./PDFBox";
 import { VideoBox } from "./VideoBox";
-import { Id } from "../../../new_fields/FieldSymbols";
+import { ScriptField } from "../../../new_fields/ScriptField";
 
 //
 // these properties get assigned through the render() method of the DocumentView when it creates this node.
@@ -32,6 +32,7 @@ export interface FieldViewProps {
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     Document: Doc;
     DataDoc?: Doc;
+    onClick?: ScriptField;
     isSelected: () => boolean;
     select: (isCtrlPressed: boolean) => void;
     renderDepth: number;
-- 
cgit v1.2.3-70-g09d2


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

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

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

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

