From 2d7037dd5664700cda04b1fb0c6c77fe6f49d66c Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Thu, 9 May 2024 23:33:17 -0400
Subject: goodbye old parser ;( hello new parser :)

---
 src/client/views/collections/collectionSchema/SchemaRowBox.tsx | 2 ++
 1 file changed, 2 insertions(+)

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

diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 760089ffb..3295c9ab1 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -52,6 +52,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         this._props.setContentViewBox?.(this);
     }
 
+    cleanupField = (field: string) => this.schemaView.cleanupComputedField(field)
     setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY);
     selectedCol = () => this.schemaView._selectedCol;
     getFinfo = computedFn((fieldKey: string) => this.schemaView?.fieldInfos.get(fieldKey));
@@ -149,6 +150,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                             setSelectedColumnValues={this.setSelectedColumnValues}
                             oneLine={BoolCast(this.schemaDoc?._singleLine)}
                             menuTarget={this.schemaView.MenuTarget}
+                            cleanupField={this.cleanupField}
                             transform={() => {
                                 const ind = index === this.schemaView.columnKeys.length - 1 ? this.schemaView.columnKeys.length - 3 : index;
                                 const x = this.schemaView?.displayColumnWidths.reduce((p, c, i) => (i <= ind ? p + c : p), 0);
-- 
cgit v1.2.3-70-g09d2


From 4770a958a7b1003d636a4f9ea2cfdb76558e61b9 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Mon, 13 May 2024 23:13:15 -0400
Subject: columnheader editing progress

---
 src/client/views/EditableView.tsx                  |   2 +-
 .../collectionSchema/CollectionSchemaView.tsx      |  11 +-
 .../collectionSchema/SchemaColumnHeader.tsx        | 144 +++++++++++----------
 .../collections/collectionSchema/SchemaRowBox.tsx  |   2 +-
 4 files changed, 88 insertions(+), 71 deletions(-)

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

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 684b948af..05c926399 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -155,7 +155,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
             case 'ArrowDown':
             case 'ArrowLeft':
             case 'ArrowRight':
-                e.stopPropagation();
+                //e.stopPropagation();
                 break;
             case 'Shift':
             case 'Alt':
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index d844fdefc..d74cb56cf 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -275,6 +275,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     changeColumnKey = (index: number, newKey: string, defaultVal?: any) => {
         if (!this.documentKeys.includes(newKey)) {
             this.addNewKey(newKey, defaultVal);
+            console.log("added")
         }
 
         const currKeys = this.columnKeys.slice(); // copy the column key array first, then change it.
@@ -745,15 +746,23 @@ export class CollectionSchemaView extends CollectionSubView() {
 
     @action
     setKey = (key: string, defaultVal?: any) => {
+        console.log("setKey called with" + key)
         if (this._makeNewColumn) {
             this.addColumn(key, defaultVal);
+            this._makeNewColumn = false;
         } else {
             this.changeColumnKey(this._columnMenuIndex!, key, defaultVal);
+            console.log("changed")
         }
         this.closeColumnMenu();
     };
 
-    setColumnValues = (key: string, value: string) => {
+    setColumnValue = () => {
+
+    }
+
+    setCellValues = (key: string, value: string) => {
+        console.log("field: " + key + " vale: " + value);
         const selectedDocs: Doc[] = [];
         this.childDocs.forEach(doc => {
             const docIsSelected = this._selectedCells && !(this._selectedCells?.filter(d => d === doc).length === 0);
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index b498a4850..b74b2ace9 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -8,11 +8,12 @@ import { emptyFunction } from '../../../../Utils';
 import { Colors } from '../../global/globalEnums';
 import './CollectionSchemaView.scss';
 import { EditableView } from '../../EditableView';
+import { ObservableReactComponent } from '../../ObservableReactComponent';
 import { DefaultStyleProvider, returnEmptyDocViewList } from '../../StyleProvider';
 import { FieldViewProps } from '../../nodes/FieldView';
 import { Doc, Field } from '../../../../fields/Doc';
 import { dropActionType } from '../../../util/DropActionTypes';
-import { Transform } from 'prosemirror-transform';
+import { Transform } from '../../../util/Transform';
 import { SchemaTableCell } from './SchemaTableCell';
 import { DocCast } from '../../../../fields/Types';
 import { computedFn } from 'mobx-utils';
@@ -48,110 +49,117 @@ export interface SchemaColumnHeaderProps {
 }
 
 @observer
-export class SchemaColumnHeader extends React.Component<SchemaColumnHeaderProps> {
+export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHeaderProps> {
 
     @observable _editing: boolean = false;
 
     get fieldKey() {
-        return this.props.columnKeys[this.props.columnIndex];
+        return this._props.columnKeys[this._props.columnIndex];
     }
 
-    // getFinfo = computedFn((fieldKey: string) => this.props.schemaView?.fieldInfos.get(fieldKey));
-    // setColumnValues = (field: string, value: string) => this.props.schemaView?.setColumnValues(field, value);
+    getFinfo = computedFn((fieldKey: string) => this._props.schemaView?.fieldInfos.get(fieldKey));
+    setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue);}
 
     @action
     sortClicked = (e: React.PointerEvent) => {
         e.stopPropagation();
         e.preventDefault();
-        if (this.props.sortField === this.fieldKey && this.props.sortDesc) {
-            this.props.setSort(undefined);
-        } else if (this.props.sortField === this.fieldKey) {
-            this.props.setSort(this.fieldKey, true);
+        if (this._props.sortField === this.fieldKey && this._props.sortDesc) {
+            this._props.setSort(undefined);
+        } else if (this._props.sortField === this.fieldKey) {
+            this._props.setSort(this.fieldKey, true);
         } else {
-            this.props.setSort(this.fieldKey, false);
+            this._props.setSort(this.fieldKey, false);
         }
     };
 
     @action
     setupDrag = (e: React.PointerEvent) => {
-        this.props.isContentActive(true) && setupMoveUpEvents(this, e, moveEv => this.props.dragColumn(moveEv, this.props.columnIndex), emptyFunction, emptyFunction);
+        this._props.isContentActive(true) && setupMoveUpEvents(this, e, moveEv => this._props.dragColumn(moveEv, this._props.columnIndex), emptyFunction, emptyFunction);
     };
 
-    // public static renderProps(props: SchemaColumnHeaderProps) {
-    //     const { columnKeys, columnWidth, isContentActive, Document } = props;
-    //     const fieldKey = columnKeys[props.columnIndex];
-    //     const color = 'black'; // color of text in cells
-    //     const fieldProps: FieldViewProps = {
-    //         childFilters: returnEmptyFilter,
-    //         childFiltersByRanges: returnEmptyFilter,
-    //         docViewPath: returnEmptyDocViewList,
-    //         searchFilterDocs: returnEmptyDoclist,
-    //         styleProvider: DefaultStyleProvider,
-    //         isSelected: returnFalse,
-    //         setHeight: returnFalse,
-    //         select: emptyFunction,
-    //         dragAction: dropActionType.move,
-    //         renderDepth: 1,
-    //         noSidebar: true,
-    //         isContentActive: returnFalse,
-    //         whenChildContentsActiveChanged: emptyFunction,
-    //         ScreenToLocalTransform: Transform.Identity,
-    //         focus: emptyFunction,
-    //         addDocTab: SchemaTableCell.addFieldDoc,
-    //         pinToPres: returnZero,
-    //         Document: DocCast(Document.rootDocument, Document),
-    //         fieldKey: fieldKey,
-    //         PanelWidth: columnWidth,
-    //         PanelHeight: props.rowHeight,
-    //         rootSelected: props.rootSelected,
-    //     };
-    //     const readOnly = getFinfo(fieldKey)?.readOnly ?? false;
-    //     const cursor = !readOnly ? 'text' : 'default';
-    //     const pointerEvents = 'all';
-    //     return { color, fieldProps, cursor, pointerEvents };
-    // }
+    renderProps = (props: SchemaColumnHeaderProps) => {
+        const { columnKeys, columnWidth, Document } = props;
+        const fieldKey = columnKeys[props.columnIndex];
+        const color = 'black'; // color of text in cells
+        const fieldProps: FieldViewProps = {
+            childFilters: returnEmptyFilter,
+            childFiltersByRanges: returnEmptyFilter,
+            docViewPath: returnEmptyDocViewList,
+            searchFilterDocs: returnEmptyDoclist,
+            styleProvider: DefaultStyleProvider,
+            isSelected: returnFalse,
+            setHeight: returnFalse,
+            select: emptyFunction,
+            dragAction: dropActionType.move,
+            renderDepth: 1,
+            noSidebar: true,
+            isContentActive: returnFalse,
+            whenChildContentsActiveChanged: emptyFunction,
+            ScreenToLocalTransform: Transform.Identity,
+            focus: emptyFunction,
+            addDocTab: SchemaTableCell.addFieldDoc,
+            pinToPres: returnZero,
+            Document: DocCast(Document.rootDocument, Document),
+            fieldKey: fieldKey,
+            PanelWidth: columnWidth,
+            PanelHeight: props.rowHeight,
+            rootSelected: props.rootSelected,
+        };
+        const readOnly = this.getFinfo(fieldKey)?.readOnly ?? false;
+        const cursor = !readOnly ? 'text' : 'default';
+        const pointerEvents = 'all';
+        return { color, fieldProps, cursor, pointerEvents };
+    }
+
+    @computed get editableView() {
+        const { color, fieldProps, pointerEvents } = this.renderProps(this._props); 
 
-    // @computed get editableView() {
-    //     const { color, fieldProps, pointerEvents } = SchemaColumnHeader.renderProps(this.props); 
+        return <div className='column-header-edit-wrapper'>
+            <EditableView
+                ref={r => this._props.autoFocus && r?.setIsFocused(true)}
+                oneLine={this._props.oneLine}
+                allowCRs={this._props.allowCRs}
+                contents={undefined}
+                fieldContents={fieldProps}
+                editing={this._editing ? undefined : false}
+                GetValue={() => Field.toKeyValueString(fieldProps.Document, this.fieldKey, SnappingManager.MetaKey).replace(/[";]/g, '')}
+                SetValue={undoable((value: string) => {
+                    this.setColumnValues(value, value);
+                    this._props.finishEdit?.();
+                    return true;
+                }, 'edit column header')}
+            />
+            </div>
+    }
 
-    //     return <EditableView
-    //             ref={r => this.props.autoFocus && r?.setIsFocused(true)}
-    //             oneLine={this.props.oneLine}
-    //             allowCRs={this.props.allowCRs}
-    //             contents={undefined}
-    //             fieldContents={fieldProps}
-    //             editing={this._editing ? undefined : false}
-    //             GetValue={() => this.props.cleanupField(Field.toKeyValueString(fieldProps.Document, this.fieldKey, SnappingManager.MetaKey)).replace(/[";]/g, '')} //TODO: feed this into parser that handles idToDoc
-    //             SetValue={undoable((value: string, enterKey?: boolean) => {
-    //                 if (enterKey) this.setColumnValues(this.fieldKey.replace(/^_/, ''), value);
-    //                 this.props.finishEdit?.();
-    //                 return true;
-    //             }, 'edit schema cell')}
-    //         />
-    // }
+    staticView = () => {
+        return <div className="schema-column-title" onPointerDown={e => {this._editing = true; console.log(this._editing)}}>{this.fieldKey}</div>
+    }
 
     render() {
         return (
             <div
                 className="schema-column-header"
                 style={{
-                    width: this.props.columnWidths[this.props.columnIndex],
+                    width: this._props.columnWidths[this._props.columnIndex],
                 }}
                 onPointerDown={this.setupDrag}
                 ref={col => {
                     if (col) {
-                        this.props.setColRef(this.props.columnIndex, col);
+                        this._props.setColRef(this._props.columnIndex, col);
                     }
                 }}>
-                <div className="schema-column-resizer left" onPointerDown={e => this.props.resizeColumn(e, this.props.columnIndex)} />
-                <div className="schema-column-title" onPointerDown={e => {this._editing = true; console.log(this._editing)}}>{this.fieldKey}</div>
+                <div className="schema-column-resizer left" onPointerDown={e => this._props.resizeColumn(e, this._props.columnIndex)} />
+
+                <div>{this._editing ? this.editableView : this.staticView()}</div>
 
                 <div className="schema-header-menu">
-                    <div className="schema-header-button" onPointerDown={e => this.props.openContextMenu(e.clientX, e.clientY, this.props.columnIndex)}>
+                    <div className="schema-header-button" onPointerDown={e => this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)}>
                         <FontAwesomeIcon icon="ellipsis-h" />
                     </div>
-                    <div className="schema-sort-button" onPointerDown={this.sortClicked} style={this.props.sortField === this.fieldKey ? { backgroundColor: Colors.MEDIUM_BLUE } : {}}>
-                        <FontAwesomeIcon icon="caret-right" style={this.props.sortField === this.fieldKey ? { transform: `rotate(${this.props.sortDesc ? '270deg' : '90deg'})` } : {}} />
+                    <div className="schema-sort-button" onPointerDown={this.sortClicked} style={this._props.sortField === this.fieldKey ? { backgroundColor: Colors.MEDIUM_BLUE } : {}}>
+                        <FontAwesomeIcon icon="caret-right" style={this._props.sortField === this.fieldKey ? { transform: `rotate(${this._props.sortDesc ? '270deg' : '90deg'})` } : {}} />
                     </div>
                 </div>
             </div>
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 3295c9ab1..908939ecc 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -59,7 +59,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
     selectCell = (doc: Doc, col: number, shift: boolean, ctrl: boolean) => this.schemaView?.selectCell(doc, col, shift, ctrl);
     deselectCell = () => this.schemaView?.deselectAllCells();
     selectedCells = () => this.schemaView?._selectedDocs;
-    setColumnValues = (field: any, value: any) => this.schemaView?.setColumnValues(field, value) ?? false;
+    setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false;
     setSelectedColumnValues = (field: any, value: any) => this.schemaView?.setSelectedColumnValues(field, value) ?? false;
     columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
     render() {
-- 
cgit v1.2.3-70-g09d2


From 1be63695875c9242fba43d580465e8765cf3991d Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Mon, 3 Jun 2024 13:33:25 -0400
Subject: merge prep

---
 .../collectionSchema/CollectionSchemaView.tsx      | 34 +++++-----------------
 .../collections/collectionSchema/SchemaRowBox.tsx  |  2 --
 .../collectionSchema/SchemaTableCell.tsx           |  1 -
 src/client/views/global/globalScripts.ts           |  2 ++
 4 files changed, 10 insertions(+), 29 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index c673f0e56..ef1819120 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -700,42 +700,24 @@ export class CollectionSchemaView extends CollectionSubView() {
 
     @action
     setKey = (key: string, defaultVal?: any, index?: number) => {
-        if (this.columnKeys.includes(key)){
-            return;
-        }
-
+        if (this.columnKeys.includes(key)) return;
+    
         if (this._makeNewColumn) {
             this.addColumn(key, defaultVal);
             this._makeNewColumn = false;
-        } else {
-            this.changeColumnKey(this._columnMenuIndex! | index!, key, defaultVal);
-        }
+        } else this.changeColumnKey(this._columnMenuIndex! | index!, key, defaultVal);
+        
         this.closeColumnMenu();
     };
 
     setCellValues = (key: string, value: string) => {
         const selectedDocs: Doc[] = [];
         this.childDocs.forEach(doc => {
-            const docIsSelected = this._selectedCells && !(this._selectedCells?.filter(d => d === doc).length === 0);
-            if (docIsSelected) {
-                selectedDocs.push(doc);
-            }
-        });
-        if (selectedDocs.length === 1) {
-            this.childDocs.forEach(doc => Doc.SetField(doc, key, value));
-        } else {
-            selectedDocs.forEach(doc => Doc.SetField(doc, key, value));
-        }
-        return true;
-    };
-
-    setSelectedColumnValues = (key: string, value: string) => {
-        this.childDocs.forEach(doc => {
-            const docIsSelected = this._selectedCells && !(this._selectedCells?.filter(d => d === doc).length === 0);
-            if (docIsSelected) {
-                Doc.SetField(doc, key, value);
-            }
+            const isSelected = this._selectedCells && !(this._selectedCells?.filter(d => d === doc).length === 0);
+            isSelected && selectedDocs.push(doc); 
         });
+        if (selectedDocs.length === 1) this.childDocs.forEach(doc => Doc.SetField(doc, key, value)); // if only one cell selected, fill all
+        else selectedDocs.forEach(doc => Doc.SetField(doc, key, value)); // else only fill selected cells
         return true;
     };
 
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 908939ecc..da272cd18 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -60,7 +60,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
     deselectCell = () => this.schemaView?.deselectAllCells();
     selectedCells = () => this.schemaView?._selectedDocs;
     setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false;
-    setSelectedColumnValues = (field: any, value: any) => this.schemaView?.setSelectedColumnValues(field, value) ?? false;
     columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
     render() {
         return (
@@ -147,7 +146,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                             selectedCells={this.selectedCells}
                             selectedCol={this.selectedCol}
                             setColumnValues={this.setColumnValues}
-                            setSelectedColumnValues={this.setSelectedColumnValues}
                             oneLine={BoolCast(this.schemaDoc?._singleLine)}
                             menuTarget={this.schemaView.MenuTarget}
                             cleanupField={this.cleanupField}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 4531f30a8..e6660f379 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -48,7 +48,6 @@ export interface SchemaTableCellProps {
     isRowActive: () => boolean | undefined;
     getFinfo: (fieldKey: string) => FInfo | undefined;
     setColumnValues: (field: string, value: string) => boolean;
-    setSelectedColumnValues: (field: string, value: string) => boolean;
     oneLine?: boolean; // whether all input should fit on one line vs allowing textare multiline inputs
     allowCRs?: boolean; // allow carriage returns in text input (othewrise CR ends the edit)
     finishEdit?: () => void; // notify container that edit is over (eg. to hide view in DashFieldView)
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
index c595681b7..8e5c39ddf 100644
--- a/src/client/views/global/globalScripts.ts
+++ b/src/client/views/global/globalScripts.ts
@@ -66,6 +66,8 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b
             } else {
                 const dataKey = Doc.LayoutFieldKey(dv.Document);
                 const alternate = (dv.layoutDoc[dataKey + '_usePath'] ? '_' + dv.layoutDoc[dataKey + '_usePath'] : '').replace(':hover', '');
+                console.log('color: ' + dv.dataDoc[fieldKey + alternate] + ' to set to: ' + color)
+                dv.layoutDoc[fieldKey + alternate] = undefined;
                 dv.dataDoc[fieldKey + alternate] = color;
             }
         });
-- 
cgit v1.2.3-70-g09d2


From fed19c3b7e14bc00216b5f91363451a0e9bed93d Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Wed, 5 Jun 2024 13:42:04 -0400
Subject: row menu rework, icons mostly good

---
 .../collectionSchema/CollectionSchemaView.tsx      | 34 ++++++----
 .../collections/collectionSchema/SchemaRowBox.tsx  | 76 ++++++++++------------
 2 files changed, 58 insertions(+), 52 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 6b97cb97c..30daa793a 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -7,11 +7,11 @@ import * as React from 'react';
 import { returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../ClientUtils';
 import { emptyFunction } from '../../../../Utils';
 import { Doc, DocListCast, Field, FieldType, IdToDoc, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
-import { DocData } from '../../../../fields/DocSymbols';
+import { AclPrivate, DocData } from '../../../../fields/DocSymbols';
 import { Id } from '../../../../fields/FieldSymbols';
 import { List } from '../../../../fields/List';
 import { ColumnType } from '../../../../fields/SchemaHeaderField';
-import { BoolCast, NumCast, StrCast } from '../../../../fields/Types';
+import { BoolCast, Cast, NumCast, StrCast } from '../../../../fields/Types';
 import { DocUtils } from '../../../documents/DocUtils';
 import { Docs, DocumentOptions, FInfo } from '../../../documents/Documents';
 import { DragManager } from '../../../util/DragManager';
@@ -34,6 +34,9 @@ import { SchemaRowBox } from './SchemaRowBox';
 import { ActionButton } from '@adobe/react-spectrum';
 import { CollectionMasonryViewFieldRow } from '../CollectionMasonryViewFieldRow';
 import { Func } from 'mocha';
+import { CollectionView } from '../CollectionView';
+import { listSpec } from '../../../../fields/Schema';
+import { GetEffectiveAcl } from '../../../../fields/util';
 
 const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore
 
@@ -635,6 +638,19 @@ export class CollectionSchemaView extends CollectionSubView() {
         return undefined;
     };
 
+    addDocsFromChildCollection = (collection: CollectionSchemaView) => {
+        const childDocs = collection.childDocs.slice();
+        console.log(childDocs)
+        childDocs.forEach((doc: Doc) => {!this.childDocs.includes(doc) && this._lentDocs.push(doc)});
+    }
+
+    removeChildCollectionDocs = (collection: CollectionSchemaView) => {
+        const children = collection.childDocs.slice();
+        this._lentDocs.forEach(element => {
+            
+        });
+    }
+
     @computed get fieldDefaultInput() {
         switch (this._newFieldType) {
             case ColumnType.Number:
@@ -746,9 +762,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         this._columnMenuIndex = index;
         this._menuValue = '';
         this._menuKeys = this.documentKeys;
-        this._makeNewField = false;
         this._newFieldWarning = '';
-        this._makeNewField = false;
         this._makeNewColumn = newCol;
     };
 
@@ -920,7 +934,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         const x = this._columnMenuIndex! === -1 ? 0 : this.displayColumnWidths.reduce((total, curr, index) => total + (index < this._columnMenuIndex! ? curr : 0), CollectionSchemaView._rowMenuWidth);
         return (
             <div className="schema-column-menu" style={{ left: x, minWidth: CollectionSchemaView._minColWidth }}>
-                {this._makeNewField ? this.newFieldMenu : this.keysDropdown}
+                {this.keysDropdown}
             </div>
         );
     }
@@ -928,7 +942,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     get renderKeysMenu() {
         return (
             <div className="schema-column-menu" style={{ left: 0, minWidth: CollectionSchemaView._minColWidth }}>
-                {this._makeNewField ? this.newFieldMenu : this.keysDropdown}
+                {this.keysDropdown}
             </div>
         );
     }
@@ -954,7 +968,7 @@ export class CollectionSchemaView extends CollectionSubView() {
             }
             return (
                 <div key={key} className="schema-filter-option">
-                    <input //
+                    <input 
                         type="checkbox"
                         onPointerDown={e => e.stopPropagation()}
                         onClick={e => e.stopPropagation()}
@@ -1025,11 +1039,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0);
     previewWidthFunc = () => this.previewWidth;
     onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
-    displayedDocsFunc = () => {
-        let docs: Doc[] = this._lentDocs.slice();
-        docs = docs.concat(this.sortedDocs.docs);
-        return docs;
-    }
+    displayedDocsFunc = () => this._lentDocs.slice().concat(this.sortedDocs.docs);
     _oldWheel: any;
     render() {
         return (
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index da272cd18..8e4161413 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -1,9 +1,9 @@
 import { IconButton, Size } from 'browndash-components';
-import { computed, makeObservable } from 'mobx';
+import { computed, makeObservable, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import { computedFn } from 'mobx-utils';
 import * as React from 'react';
-import { CgClose, CgLock, CgLockUnlock } from 'react-icons/cg';
+import { CgClose, CgLock, CgLockUnlock, CgMenu } from 'react-icons/cg';
 import { FaExternalLinkAlt } from 'react-icons/fa';
 import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils';
 import { emptyFunction } from '../../../../Utils';
@@ -18,6 +18,8 @@ import { OpenWhere } from '../../nodes/OpenWhere';
 import { CollectionSchemaView } from './CollectionSchemaView';
 import './CollectionSchemaView.scss';
 import { SchemaTableCell } from './SchemaTableCell';
+import { ContextMenu } from '../../ContextMenu';
+import { CollectionFreeFormView } from '../collectionFreeForm';
 
 interface SchemaRowBoxProps extends FieldViewProps {
     rowIndex: number;
@@ -28,6 +30,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         return FieldView.LayoutString(SchemaRowBox, fieldKey).replace('fieldKey', `rowIndex={${rowIndex}} fieldKey`);
     }
     private _ref: HTMLDivElement | null = null;
+    @observable _childrenAddedToSchema: boolean = false;
 
     constructor(props: SchemaRowBoxProps) {
         super(props);
@@ -52,6 +55,33 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         this._props.setContentViewBox?.(this);
     }
 
+    openContextMenu = (x: number, y: number) => {
+        ContextMenu.Instance.clearItems();
+        ContextMenu.Instance.addItem({
+            description: `Close doc`,
+            event: () => this._props.removeDocument?.(this.Document),
+            icon: 'minus',
+        });
+        ContextMenu.Instance.addItem({
+            description: this.Document._lockedPosition ? 'Unlock doc interactions' : 'Lock doc interactions',
+            event: () => Doc.toggleLockedPosition(this.Document),
+            icon: this.Document._lockedPosition ? 'lock-open' : 'lock',
+        });
+        ContextMenu.Instance.addItem({
+            description: 'Open preview',
+            event: () => this._props.addDocTab(this.Document, OpenWhere.addRight),
+            icon: 'magnifying-glass',
+        });
+        if (this.Document['type'] === 'collection') {
+                ContextMenu.Instance.addItem({
+                description: 'Add children to schema',
+                event: () => this.schemaView.addDocsFromChildCollection(this.Document as unknown as CollectionSchemaView),
+                icon: 'plus',
+            });
+        }
+        ContextMenu.Instance.displayMenu(x, y, undefined, false);
+    }
+
     cleanupField = (field: string) => this.schemaView.cleanupComputedField(field)
     setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY);
     selectedCol = () => this.schemaView._selectedCol;
@@ -78,42 +108,8 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                         pointerEvents: !this._props.isContentActive() ? 'none' : undefined,
                     }}>
                     <IconButton
-                        tooltip="close"
-                        icon={<CgClose size="16px" />}
-                        size={Size.XSMALL}
-                        onPointerDown={e =>
-                            setupMoveUpEvents(
-                                this,
-                                e,
-                                returnFalse,
-                                emptyFunction,
-                                undoable(clickEv => {
-                                    clickEv.stopPropagation();
-                                    this._props.removeDocument?.(this.Document);
-                                }, 'Delete Row')
-                            )
-                        }
-                    />
-                    <IconButton
-                        tooltip="whether document interactions are enabled"
-                        icon={this.Document._lockedPosition ? <CgLockUnlock size="12px" /> : <CgLock size="12px" />}
-                        size={Size.XSMALL}
-                        onPointerDown={e =>
-                            setupMoveUpEvents(
-                                this,
-                                e,
-                                returnFalse,
-                                emptyFunction,
-                                undoable(clickEv => {
-                                    clickEv.stopPropagation();
-                                    Doc.toggleLockedPosition(this.Document);
-                                }, 'toggle document lock')
-                            )
-                        }
-                    />
-                    <IconButton
-                        tooltip="open preview"
-                        icon={<FaExternalLinkAlt />}
+                        tooltip="Open actions menu"
+                        icon={ <CgMenu size="12px" /> }
                         size={Size.XSMALL}
                         onPointerDown={e =>
                             setupMoveUpEvents(
@@ -123,8 +119,8 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                                 emptyFunction,
                                 undoable(clickEv => {
                                     clickEv.stopPropagation();
-                                    this._props.addDocTab(this.Document, OpenWhere.addRight);
-                                }, 'Open schema Doc preview')
+                                    this.openContextMenu(e.clientX, e.clientY)
+                                }, 'open actions menu')
                             )
                         }
                     />
-- 
cgit v1.2.3-70-g09d2


From 9d0576378416b2e4ce7c5eb3c958ec6a650e9f90 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Wed, 5 Jun 2024 23:15:35 -0400
Subject: c

---
 src/client/documents/Documents.ts                  |  1 +
 .../collectionSchema/CollectionSchemaView.tsx      | 26 +++++++++++-----------
 .../collections/collectionSchema/SchemaRowBox.tsx  | 10 ++++++---
 3 files changed, 21 insertions(+), 16 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index c34a833f8..365af66b7 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -227,6 +227,7 @@ export class DocumentOptions {
     _header_pointerEvents?: PEVt = new PEInfo('types of events the header of a custom text document can consume');
     _lockedPosition?: BOOLt = new BoolInfo("lock the x,y coordinates of the document so that it can't be dragged");
     _lockedTransform?: BOOLt = new BoolInfo('lock the freeform_panx,freeform_pany and scale parameters of the document so that it be panned/zoomed');
+    _childrenSharedWithSchema?: BOOLt = new BoolInfo("whether this document's children are displayed in its parent schema view");
 
     dataViz_title?: string;
     dataViz_line?: string;
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 30daa793a..39bde7d37 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -147,7 +147,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     }
 
     @computed get rowHeights() {
-        return this.childDocs.map(() => this.rowHeightFunc());
+        return this.childDocs.concat(this._lentDocs).map(() => this.rowHeightFunc());
     }
 
     @computed get displayColumnWidths() {
@@ -584,7 +584,8 @@ export class CollectionSchemaView extends CollectionSubView() {
 
         const draggedDocs = de.complete.docDragData?.draggedDocuments;
         if (draggedDocs && super.onInternalDrop(e, de) && !this.sortField) {
-            const map = draggedDocs?.map(doc => this.rowIndex(doc));
+            const sortedDocs = this.sortedDocs.docs.slice();
+const       filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs.includes(doc));
             this.dataDoc[this.fieldKey ?? 'data'] = new List<Doc>([...this.sortedDocs.docs]);
             this.clearSelection();
             draggedDocs.forEach(doc => {
@@ -638,17 +639,16 @@ export class CollectionSchemaView extends CollectionSubView() {
         return undefined;
     };
 
-    addDocsFromChildCollection = (collection: CollectionSchemaView) => {
-        const childDocs = collection.childDocs.slice();
-        console.log(childDocs)
-        childDocs.forEach((doc: Doc) => {!this.childDocs.includes(doc) && this._lentDocs.push(doc)});
+    addDocsFromChildCollection = (collection: Doc) => {
+        const childDocs = DocListCast(collection[Doc.LayoutFieldKey(collection)]);
+        childDocs.forEach((doc: Doc) => {!this.displayedDocsFunc().includes(doc) && this._lentDocs.push(doc)});
     }
 
-    removeChildCollectionDocs = (collection: CollectionSchemaView) => {
-        const children = collection.childDocs.slice();
-        this._lentDocs.forEach(element => {
-            
-        });
+    removeChildCollectionDocs = (collection: Doc) => {
+        const children = DocListCast(collection[Doc.LayoutFieldKey(collection)]);
+        console.log('before: ' + this._lentDocs)
+        this._lentDocs.filter((doc: Doc) => !children.includes(doc));
+        console.log('after: ' + this._lentDocs)
     }
 
     @computed get fieldDefaultInput() {
@@ -1016,7 +1016,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : [];
         const field = StrCast(this.layoutDoc.sortField);
         const desc = BoolCast(this.layoutDoc.sortDesc); // is this an ascending or descending sort
-        const staticDocs = this.childDocs.filter(d => !draggedDocs.includes(d));
+        const staticDocs = this.childDocs.filter(d => !draggedDocs.includes(d)).concat(this._lentDocs.filter(d => !draggedDocs.includes(d)));
         const docs = !field
             ? staticDocs
             : [...staticDocs].sort((docA, docB) => {
@@ -1039,7 +1039,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0);
     previewWidthFunc = () => this.previewWidth;
     onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
-    displayedDocsFunc = () => this._lentDocs.slice().concat(this.sortedDocs.docs);
+    displayedDocsFunc = () => this.sortedDocs.docs;
     _oldWheel: any;
     render() {
         return (
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 8e4161413..8ac2c0314 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -74,9 +74,13 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         });
         if (this.Document['type'] === 'collection') {
                 ContextMenu.Instance.addItem({
-                description: 'Add children to schema',
-                event: () => this.schemaView.addDocsFromChildCollection(this.Document as unknown as CollectionSchemaView),
-                icon: 'plus',
+                description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema',
+                event: () => {
+                    this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; 
+                    this.Document._childrenSharedWithSchema ? 
+                    this.schemaView.addDocsFromChildCollection(this.Document) : this.schemaView.removeChildCollectionDocs(this.Document);
+                },
+                icon: this.Document._childrenSharedWithSchema ? 'minus' : 'plus',
             });
         }
         ContextMenu.Instance.displayMenu(x, y, undefined, false);
-- 
cgit v1.2.3-70-g09d2


From a9ec444d00a02a5e04f3c022fd4d0bea08efe196 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Fri, 7 Jun 2024 02:36:18 -0400
Subject: lots of UI improvements

---
 src/client/views/EditableView.tsx                  | 16 +++++++------
 .../collectionSchema/CollectionSchemaView.scss     |  4 ----
 .../collectionSchema/CollectionSchemaView.tsx      |  2 ++
 .../collectionSchema/SchemaColumnHeader.tsx        | 19 ++++++++-------
 .../collections/collectionSchema/SchemaRowBox.tsx  |  3 ++-
 .../collectionSchema/SchemaTableCell.tsx           | 27 ++++++++++++++++++----
 6 files changed, 46 insertions(+), 25 deletions(-)

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

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index c79cabd6a..5b690bf33 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -55,7 +55,7 @@ export interface EditableProps {
     placeholder?: string;
     wrap?: string; // nowrap, pre-wrap, etc
 
-    showKeyNotVal?: boolean;
+    schemaHeader?: boolean;
     updateAlt?: (newAlt: string) => void;
     updateSearch?: (value: string) => void;
 }
@@ -77,6 +77,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
         super(props);
         makeObservable(this);
         this._editing = !!this._props.editing;
+        if (this._props.schemaHeader) this._editing = true;
     }
 
     componentDidMount(): void {
@@ -184,9 +185,9 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
     };
 
     @action
-    onClick = (e: React.MouseEvent) => {
+    onClick = (e?: React.MouseEvent) => {
         if (this._props.editing !== false) {
-            e.nativeEvent.stopPropagation();
+            e?.nativeEvent.stopPropagation();
             if (this._ref.current && this._props.showMenuOnLoad) {
                 this._props.menuCallback?.(this._ref.current.getBoundingClientRect().x, this._ref.current.getBoundingClientRect().y);
             } else {
@@ -280,12 +281,13 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
         );
     }
 
-    display = () => {
+    staticDisplay = () => {
         let toDisplay;
         const gval = this._props.GetValue()?.replace(/\n/g, '\\r\\n');
-        if (this._props.showKeyNotVal){
+        if (this._props.schemaHeader){
             toDisplay = <input className="editableView-input"
-            value={this._props.GetValue()}
+            value={gval}
+            placeholder='Add key'
             readOnly
             style={{ display: this._props.display, overflow: 'auto', pointerEvents: 'none', fontSize: this._props.fontSize, width: '100%', margin: 0, background: this._props.background}}
             // eslint-disable-next-line jsx-a11y/no-autofocus
@@ -335,7 +337,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
                     fontSize: this._props.fontSize,
                 }}
                 onClick={this.onClick}>
-                {this.display()}
+                {this.staticDisplay()}
             </div>
         );
     }
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
index 3d89a479a..ceffc7e44 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
@@ -302,7 +302,3 @@
     }
 }
 
-.header-dropdown-container {
-    height: 0px;
-    width: 60px;
-}
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 39bde7d37..ec1341b14 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -758,6 +758,8 @@ const       filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs.
 
     @action
     openColumnMenu = (index: number, newCol: boolean) => {
+        this.closeFilterMenu();
+        
         this._makeNewColumn = false;
         this._columnMenuIndex = index;
         this._menuValue = '';
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 03cf64fc8..bda9fc9b7 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -57,6 +57,11 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
     @computed get fieldKey() {
         return this._props.columnKeys[this._props.columnIndex];
     }
+
+    constructor(props: SchemaColumnHeaderProps){
+        super(props);
+        this._props.schemaView.openColumnMenu(0, false)
+    }
     
     getFinfo = computedFn((fieldKey: string) => this._props.schemaView?.fieldInfos.get(fieldKey));
     setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);}
@@ -77,10 +82,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
     };
 
     openKeyDropdown = () => {
-        if (this.isDefaultTitle(this.fieldKey)){
-            this._props.schemaView.openColumnMenu(this._props.columnIndex, false)
-            this._displayKeysDropdown = true;
-        }
+        this._props.schemaView.openColumnMenu(this._props.columnIndex, false)
     }
 
     @action
@@ -125,7 +127,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
     @computed get editableView() {
         const { color, fieldProps, pointerEvents } = this.renderProps(this._props); 
 
-        return <div className='schema-column-edit-wrapper' onPointerUp={() => this.openKeyDropdown()}
+        return <div className='schema-column-edit-wrapper' onPointerUp={() => {SchemaColumnHeader.isDefaultField(this.fieldKey) && this.openKeyDropdown()}}
         style={{
             color,
             width: '100%',
@@ -138,11 +140,12 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
                 contents={undefined}
                 fieldContents={fieldProps}
                 editing={undefined}  
+                placeholder={'Add key'}
                 updateAlt={this.updateAlt} // alternate title to display
                 updateSearch={this.updateKeyDropdown}
-                showKeyNotVal={true} // tells the EditableView to display the fieldKey itself, and not its value
+                schemaHeader={true} 
                 GetValue={() => {
-                    if (this.isDefaultTitle(this.fieldKey)) return '';
+                    if (SchemaColumnHeader.isDefaultField(this.fieldKey)) return '';
                     else if (this._altTitle) return this._altTitle;
                     else return this.fieldKey;
                 }}
@@ -160,7 +163,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
             </div>
     }
 
-    isDefaultTitle = (key: string) => {
+    public static isDefaultField = (key: string) => {
         const defaultPattern = /EmptyColumnKey/;
         let isDefault: boolean = (defaultPattern.exec(key) != null);
         return isDefault;
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 8ac2c0314..8cac302ce 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -113,7 +113,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                     }}>
                     <IconButton
                         tooltip="Open actions menu"
-                        icon={ <CgMenu size="12px" /> }
+                        icon={ <CgMenu size="16px" /> }
                         size={Size.XSMALL}
                         onPointerDown={e =>
                             setupMoveUpEvents(
@@ -133,6 +133,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                     {this.schemaView?.columnKeys?.map((key, index) => (
                         <SchemaTableCell
                             key={key}
+                            rowSelected={this._props.isSelected}
                             Document={this.Document}
                             col={index}
                             fieldKey={key}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index c3a58b505..dc060218c 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -32,6 +32,7 @@ import { FieldViewProps } from '../../nodes/FieldView';
 import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
 import { CollectionSchemaView, FInfotoColType } from './CollectionSchemaView';
 import './CollectionSchemaView.scss';
+import { SchemaColumnHeader } from './SchemaColumnHeader';
 
 export interface SchemaTableCellProps {
     Document: Doc;
@@ -57,12 +58,13 @@ export interface SchemaTableCellProps {
     autoFocus?: boolean; // whether to set focus on creation, othwerise wait for a click
     rootSelected?: () => boolean;
     cleanupField: (field: string) => string;
+    rowSelected: () => boolean;
 }
 
 function selectedCell(props: SchemaTableCellProps) {
     return (
         props.isRowActive() &&
-        props.selectedCol() === props.col && //
+        props.selectedCol() === props.col && 
         props.selectedCells()?.filter(d => d === props.Document)?.length
     );
 }
@@ -74,6 +76,10 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         makeObservable(this);
     }
 
+    get defaultKey(){
+        return SchemaColumnHeader.isDefaultField(this._props.fieldKey)
+    }
+
     static addFieldDoc = (docs: Doc | Doc[] /* , where: OpenWhere */) => {
         DocumentView.FocusOrOpen(toList(docs)[0]);
         return true;
@@ -89,9 +95,8 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
             protoCount++;
             doc = DocCast(doc.proto);
         }
-        const parenCount = Math.max(0, protoCount - 1);
         const color = protoCount === 0 || (fieldKey.startsWith('_') && Document[fieldKey] === undefined) ? 'black' : 'blue'; // color of text in cells
-        const textDecoration = color !== 'black' && parenCount ? 'underline' : '';
+        const textDecoration = '';
         const fieldProps: FieldViewProps = {
             childFilters: returnEmptyFilter,
             childFiltersByRanges: returnEmptyFilter,
@@ -185,6 +190,14 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         }
     }
 
+    get backgroundColor(){
+        if (this.defaultKey){
+            if (this._props.rowSelected()) return '#B0D1E7'
+            else return '#F5F5F5'
+        }   
+        return ''
+    }
+
     render() {
         return (
             <div
@@ -200,8 +213,12 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                         } else !selectedCell(this._props) && this._props.selectCell(this._props.Document, this._props.col, shift, ctrl);
                     }
                 })}
-                style={{ padding: this._props.padding, maxWidth: this._props.maxWidth?.(), width: this._props.columnWidth() || undefined, border: selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined }}>
-                {this.content}
+                style={{ padding: this._props.padding, 
+                maxWidth: this._props.maxWidth?.(), 
+                width: this._props.columnWidth() || undefined, 
+                border: selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined,
+                backgroundColor: this.backgroundColor}}>
+                {this.defaultKey ? '' : this.content}
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From c8dc7104f8a4923bcfc70dcc5ff5f492666487bd Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Fri, 7 Jun 2024 02:56:22 -0400
Subject: add col button tooltip + row menu icon change

---
 .../collectionSchema/CollectionSchemaView.tsx      | 30 ++++++++++++++--------
 .../collections/collectionSchema/SchemaRowBox.tsx  |  4 ++-
 2 files changed, 22 insertions(+), 12 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index ec1341b14..03e7ed5f3 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1,6 +1,6 @@
 /* eslint-disable no-restricted-syntax */
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Popup, PopupTrigger, Type } from 'browndash-components';
+import { IconButton, Popup, PopupTrigger, Size, Type } from 'browndash-components';
 import { ObservableMap, action, autorun, computed, makeObservable, observable, observe, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
@@ -759,7 +759,7 @@ const       filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs.
     @action
     openColumnMenu = (index: number, newCol: boolean) => {
         this.closeFilterMenu();
-        
+
         this._makeNewColumn = false;
         this._columnMenuIndex = index;
         this._menuValue = '';
@@ -1061,15 +1061,23 @@ const       filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs.
                     }}>
                     <div className="schema-header-row" style={{ height: this.rowHeightFunc() }}>
                         <div className="row-menu" style={{ width: CollectionSchemaView._rowMenuWidth }}>
-                            <Popup
-                                placement="right"
-                                background={SettingsManager.userBackgroundColor}
-                                color={SettingsManager.userColor}
-                                toggle={<FontAwesomeIcon onPointerDown={() => this.addColumn()} icon="plus" />} //here
-                                trigger={PopupTrigger.CLICK}
-                                type={Type.TERT}
-                                isOpen={this._columnMenuIndex !== -1 ? false : undefined}
-                                popup={this.renderKeysMenu}
+                            <IconButton
+                            tooltip="Add a new key"
+                            icon={ <FontAwesomeIcon icon="plus" size='lg'/>}
+                            size={Size.XSMALL}
+                            color={'black'}
+                            onPointerDown={e =>
+                                setupMoveUpEvents(
+                                    this,
+                                    e,
+                                    returnFalse,
+                                    emptyFunction,
+                                    undoable(clickEv => {
+                                        clickEv.stopPropagation();
+                                        this.addColumn()
+                                    }, 'add key to schema')
+                                )
+                            }
                             />
                         </div>
                         {this.columnKeys.map((key, index) => (
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 8cac302ce..099670022 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -20,6 +20,7 @@ import './CollectionSchemaView.scss';
 import { SchemaTableCell } from './SchemaTableCell';
 import { ContextMenu } from '../../ContextMenu';
 import { CollectionFreeFormView } from '../collectionFreeForm';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 
 interface SchemaRowBoxProps extends FieldViewProps {
     rowIndex: number;
@@ -113,8 +114,9 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                     }}>
                     <IconButton
                         tooltip="Open actions menu"
-                        icon={ <CgMenu size="16px" /> }
+                        icon={ <FontAwesomeIcon icon="list" size='lg'/>}
                         size={Size.XSMALL}
+                        color={'black'}
                         onPointerDown={e =>
                             setupMoveUpEvents(
                                 this,
-- 
cgit v1.2.3-70-g09d2


From 97977e7156eb852c20422fa995bbf96529dfb4e5 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Fri, 7 Jun 2024 19:36:59 -0400
Subject: sort overhaul for columnheader menu cleanup (sort is now a single
 action, not a persistent toggle; more like google sheets now)

---
 src/client/views/EditableView.scss                 |   3 +-
 src/client/views/EditableView.tsx                  |   5 +-
 src/client/views/MainView.tsx                      |   3 +
 .../collectionSchema/CollectionSchemaView.tsx      | 106 +++++++++++----------
 .../collectionSchema/SchemaColumnHeader.tsx        |  16 ----
 .../collections/collectionSchema/SchemaRowBox.tsx  |   7 +-
 6 files changed, 69 insertions(+), 71 deletions(-)

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

diff --git a/src/client/views/EditableView.scss b/src/client/views/EditableView.scss
index e492068c8..d2f11f5e1 100644
--- a/src/client/views/EditableView.scss
+++ b/src/client/views/EditableView.scss
@@ -34,9 +34,8 @@
     pointer-events: all;
 }
 
-
-
 .editableView-input:focus {
     border: none;
     outline: none;
 }
+
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 5b690bf33..1652e6cd7 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -10,6 +10,7 @@ import { DocumentIconContainer } from './nodes/DocumentIcon';
 import { FieldView, FieldViewProps } from './nodes/FieldView';
 import { ObservableReactComponent } from './ObservableReactComponent';
 import { OverlayView } from './OverlayView';
+import { Padding } from 'browndash-components';
 
 export interface EditableProps {
     /**
@@ -293,10 +294,10 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
             // eslint-disable-next-line jsx-a11y/no-autofocus
         />
         } else {
-            toDisplay = (<span
+            toDisplay = (<span className='editableView-static'
             style={{
                 fontStyle: this._props.fontStyle,
-                fontSize: this._props.fontSize,
+                fontSize: this._props.fontSize
             }}>
             {
                 // eslint-disable-next-line react/jsx-props-no-spreading
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 31d88fb87..5fe9332f4 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -278,6 +278,9 @@ export class MainView extends ObservableReactComponent<{}> {
 
         library.add(
             ...[
+                fa.faSort,
+                fa.faArrowUpZA,
+                fa.faArrowDownAZ,
                 fa.faExclamationCircle,
                 fa.faEdit,
                 fa.faArrowDownShortWide,
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 03e7ed5f3..a2f88eb80 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -37,6 +37,7 @@ import { Func } from 'mocha';
 import { CollectionView } from '../CollectionView';
 import { listSpec } from '../../../../fields/Schema';
 import { GetEffectiveAcl } from '../../../../fields/util';
+import { ContextMenuProps } from '../../ContextMenuItem';
 
 const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore
 
@@ -96,6 +97,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     @observable _colKeysFiltered: boolean = false;
     @observable _cellTags: ObservableMap = new ObservableMap<Doc, Array<string>>();
     @observable _lentDocs: Doc[] = [];
+    @observable _docs: Doc[] = this.childDocs;
 
     // target HTMLelement portal for showing a popup menu to edit cell values.
     public get MenuTarget() {
@@ -195,7 +197,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     // ViewBoxInterface overrides
     override isUnstyledView = returnTrue; // used by style provider : turns off  opacity, animation effects, scaling
 
-    rowIndex = (doc: Doc) => this.sortedDocs.docs.indexOf(doc);
+    rowIndex = (doc: Doc) => this.displayedDocs.docs.indexOf(doc);
 
     @action
     onKeyDown = (e: KeyboardEvent) => {
@@ -205,9 +207,9 @@ export class CollectionSchemaView extends CollectionSubView() {
                     {
                         const lastDoc = this._selectedDocs.lastElement();
                         const lastIndex = this.rowIndex(lastDoc);
-                        const curDoc = this.sortedDocs.docs[lastIndex];
+                        const curDoc = this.displayedDocs.docs[lastIndex];
                         if (lastIndex >= 0 && lastIndex < this.childDocs.length - 1) {
-                            const newDoc = this.sortedDocs.docs[lastIndex + 1];
+                            const newDoc = this.displayedDocs.docs[lastIndex + 1];
                             if (this._selectedDocs.includes(newDoc)) {
                                 DocumentView.DeselectView(DocumentView.getFirstDocumentView(curDoc));
                                 this.deselectCell(curDoc);
@@ -224,9 +226,9 @@ export class CollectionSchemaView extends CollectionSubView() {
                     {
                         const firstDoc = this._selectedDocs.lastElement();
                         const firstIndex = this.rowIndex(firstDoc);
-                        const curDoc = this.sortedDocs.docs[firstIndex];
+                        const curDoc = this.displayedDocs.docs[firstIndex];
                         if (firstIndex > 0 && firstIndex < this.childDocs.length) {
-                            const newDoc = this.sortedDocs.docs[firstIndex - 1];
+                            const newDoc = this.displayedDocs.docs[firstIndex - 1];
                             if (this._selectedDocs.includes(newDoc)) {
                                 DocumentView.DeselectView(DocumentView.getFirstDocumentView(curDoc));
                                 this.deselectCell(curDoc);
@@ -269,12 +271,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     @action
     changeSelectedCellColumn = () => {};
 
-    @undoBatch
-    setColumnSort = (field: string | undefined, desc: boolean = false) => {
-        this.layoutDoc.sortField = field;
-        this.layoutDoc.sortDesc = desc;
-    };
-
     addRow = (doc: Doc | Doc[]) => this.addDocument(doc);
 
     @undoBatch
@@ -512,7 +508,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         const startRow = Math.min(lastSelectedRow, index);
         const endRow = Math.max(lastSelectedRow, index);
         for (let i = startRow; i <= endRow; i++) {
-            const currDoc = this.sortedDocs.docs[i];
+            const currDoc = this.displayedDocs.docs[i];
             if (!this._selectedDocs.includes(currDoc)) {
                 this.selectCell(currDoc, this._selectedCol, false, true);
             }
@@ -552,7 +548,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         this._lowestSelectedIndex = -1;
     };
 
-    sortedSelectedDocs = () => this.sortedDocs.docs.filter(doc => this._selectedDocs.includes(doc));
+    sortedSelectedDocs = () => this.displayedDocs.docs.filter(doc => this._selectedDocs.includes(doc));
 
     @computed
     get rowDropIndex() {
@@ -584,9 +580,8 @@ export class CollectionSchemaView extends CollectionSubView() {
 
         const draggedDocs = de.complete.docDragData?.draggedDocuments;
         if (draggedDocs && super.onInternalDrop(e, de) && !this.sortField) {
-            const sortedDocs = this.sortedDocs.docs.slice();
-const       filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs.includes(doc));
-            this.dataDoc[this.fieldKey ?? 'data'] = new List<Doc>([...this.sortedDocs.docs]);
+            const docs = this.displayedDocs.docs.slice();
+            this._docs = docs;
             this.clearSelection();
             draggedDocs.forEach(doc => {
                 DocumentView.addViewRenderedCb(doc, dv => dv.select(true));
@@ -639,16 +634,13 @@ const       filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs.
         return undefined;
     };
 
-    addDocsFromChildCollection = (collection: Doc) => {
-        const childDocs = DocListCast(collection[Doc.LayoutFieldKey(collection)]);
-        childDocs.forEach((doc: Doc) => {!this.displayedDocsFunc().includes(doc) && this._lentDocs.push(doc)});
+    addDocsFromOtherCollection = (docs: Doc[]) => {
+        docs.forEach((doc: Doc) => {!this.displayedDocsFunc().includes(doc) && this._lentDocs.push(doc)});
+        this._docs = this.childDocs.slice().concat(this._lentDocs);
     }
-
-    removeChildCollectionDocs = (collection: Doc) => {
-        const children = DocListCast(collection[Doc.LayoutFieldKey(collection)]);
-        console.log('before: ' + this._lentDocs)
-        this._lentDocs.filter((doc: Doc) => !children.includes(doc));
-        console.log('after: ' + this._lentDocs)
+    removeDocsFromOtherCollection = (docs: Doc[]) => {
+        this._lentDocs.filter((doc: Doc) => !docs.includes(doc));
+        this._docs = this.childDocs.slice().concat(this._lentDocs);
     }
 
     @computed get fieldDefaultInput() {
@@ -784,27 +776,46 @@ const       filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs.
         this._filterColumnIndex = undefined;
     };
 
+    @undoBatch
+    setColumnSort = (field: string | undefined, desc: boolean = false) => {
+        this.layoutDoc.sortField = field;
+        this.layoutDoc.sortDesc = desc;
+    };
+
     openContextMenu = (x: number, y: number, index: number) => {
         this.closeColumnMenu();
         this.closeFilterMenu();
+        const cm = ContextMenu.Instance;
+        cm.clearItems();
 
-        ContextMenu.Instance.clearItems();
-        ContextMenu.Instance.addItem({
+        const revealOptions = cm.findByDescription('Sort column')
+        const sortOptions: ContextMenuProps[] = revealOptions && revealOptions && 'subitems' in revealOptions ? revealOptions.subitems : [];
+        sortOptions.push({description: 'Sort A-Z',     event: () => this.sortDocs(this._docs, this.columnKeys[index], false),     icon: 'arrow-down-a-z',}); // prettier-ignore
+        sortOptions.push({description: 'Sort Z-A',     event: () => this.sortDocs(this._docs, this.columnKeys[index], true),     icon: 'arrow-up-z-a'}); // prettier-ignore
+    
+        cm.addItem({
             description: `Change field`,
             event: () => this.openColumnMenu(index, false),
             icon: 'pencil-alt',
         });
-        ContextMenu.Instance.addItem({
+        cm.addItem({
             description: 'Filter field',
             event: () => this.openFilterMenu(index),
             icon: 'filter',
         });
-        ContextMenu.Instance.addItem({
+        cm.addItem({ 
+            description: 'Sort column', 
+            addDivider: false, 
+            noexpand: true, 
+            subitems: sortOptions, 
+            icon: 'sort' 
+        });
+        cm.addItem({
             description: 'Delete column',
             event: () => this.removeColumn(index),
             icon: 'trash',
         });
-        ContextMenu.Instance.displayMenu(x, y, undefined, false);
+        cm.displayMenu(x, y, undefined, false);
     };
 
     @action
@@ -1014,34 +1025,33 @@ const       filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs.
         }
     };
 
-    @computed get sortedDocs() {
+    @computed get displayedDocs() {
         const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : [];
-        const field = StrCast(this.layoutDoc.sortField);
-        const desc = BoolCast(this.layoutDoc.sortDesc); // is this an ascending or descending sort
-        const staticDocs = this.childDocs.filter(d => !draggedDocs.includes(d)).concat(this._lentDocs.filter(d => !draggedDocs.includes(d)));
-        const docs = !field
-            ? staticDocs
-            : [...staticDocs].sort((docA, docB) => {
-                  // this sorts the documents based on the selected field.  returning -1 for a before b, 0 for a = b, 1 for a > b
-                  const aStr = Field.toString(docA[field] as FieldType);
-                  const bStr = Field.toString(docB[field] as FieldType);
-                  let out = 0;
-                  if (aStr < bStr) out = -1;
-                  if (aStr > bStr) out = 1;
-                  if (desc) out *= -1;
-                  return out;
-              });
-
+        const docs = this._docs.filter(d => !draggedDocs.includes(d));
         docs.splice(this.rowDropIndex, 0, ...draggedDocs);
         return { docs };
     }
 
+    @action
+    sortDocs = (docs: Doc[], field: string, desc: boolean) => {
+        docs = docs.sort((docA, docB) => {
+            // this sorts the documents based on the selected field.  returning -1 for a before b, 0 for a = b, 1 for a > b
+            const aStr = Field.toString(docA[field] as FieldType);
+            const bStr = Field.toString(docB[field] as FieldType);
+            let out = 0;
+            if (aStr < bStr) out = -1;
+            if (aStr > bStr) out = 1;
+            if (desc) out *= -1;
+            return out;
+        });
+    }
+
     rowHeightFunc = () => (BoolCast(this.layoutDoc._schema_singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight);
     isContentActive = () => this._props.isSelected() || this._props.isContentActive();
     screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0);
     previewWidthFunc = () => this.previewWidth;
     onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
-    displayedDocsFunc = () => this.sortedDocs.docs;
+    displayedDocsFunc = () => this.displayedDocs.docs;
     _oldWheel: any;
     render() {
         return (
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index bda9fc9b7..dd4a13776 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -68,19 +68,6 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
     @action updateAlt = (newAlt: string) => {this._altTitle = newAlt;}
     @action updateKeyDropdown = (value: string) => {this._props.schemaView.updateKeySearch(value)}
 
-    @action
-    sortClicked = (e: React.PointerEvent) => {
-        e.stopPropagation();
-        e.preventDefault();
-        if (this._props.sortField === this.fieldKey && this._props.sortDesc) {
-            this._props.setSort(undefined);
-        } else if (this._props.sortField === this.fieldKey) {
-            this._props.setSort(this.fieldKey, true);
-        } else {
-            this._props.setSort(this.fieldKey, false);
-        }
-    };
-
     openKeyDropdown = () => {
         this._props.schemaView.openColumnMenu(this._props.columnIndex, false)
     }
@@ -190,9 +177,6 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
                         <div className="schema-header-button" onPointerDown={e => this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)}>
                             <FontAwesomeIcon icon="ellipsis-h" />
                         </div>
-                        <div className="schema-sort-button" onPointerDown={this.sortClicked} style={this._props.sortField === this.fieldKey ? { backgroundColor: Colors.MEDIUM_BLUE } : {}}>
-                            <FontAwesomeIcon icon="caret-right" style={this._props.sortField === this.fieldKey ? { transform: `rotate(${this._props.sortDesc ? '270deg' : '90deg'})` } : {}} />
-                        </div>
                     </div>
                 </div>
         );
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 099670022..665704de1 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -7,7 +7,7 @@ import { CgClose, CgLock, CgLockUnlock, CgMenu } from 'react-icons/cg';
 import { FaExternalLinkAlt } from 'react-icons/fa';
 import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils';
 import { emptyFunction } from '../../../../Utils';
-import { Doc } from '../../../../fields/Doc';
+import { Doc, DocListCast } from '../../../../fields/Doc';
 import { BoolCast } from '../../../../fields/Types';
 import { Transform } from '../../../util/Transform';
 import { undoable } from '../../../util/UndoManager';
@@ -73,13 +73,14 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
             event: () => this._props.addDocTab(this.Document, OpenWhere.addRight),
             icon: 'magnifying-glass',
         });
-        if (this.Document['type'] === 'collection') {
+        const childDocs = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)])
+        if (this.Document['type'] === 'collection' && childDocs.length) {
                 ContextMenu.Instance.addItem({
                 description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema',
                 event: () => {
                     this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; 
                     this.Document._childrenSharedWithSchema ? 
-                    this.schemaView.addDocsFromChildCollection(this.Document) : this.schemaView.removeChildCollectionDocs(this.Document);
+                    this.schemaView.addDocsFromOtherCollection(childDocs) : this.schemaView.removeDocsFromOtherCollection(childDocs);
                 },
                 icon: this.Document._childrenSharedWithSchema ? 'minus' : 'plus',
             });
-- 
cgit v1.2.3-70-g09d2


From 99b0ce24e4d56100746016995c20f9bb9c109072 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Mon, 10 Jun 2024 04:01:01 -0400
Subject: adding/removing children from collection works (probably buggy);
 backspace delete broken

---
 src/client/documents/Documents.ts                  |  2 +-
 .../collectionSchema/CollectionSchemaView.tsx      | 34 ++++++++++++++++++----
 .../collectionSchema/SchemaColumnHeader.tsx        | 23 +++++++++++++--
 .../collections/collectionSchema/SchemaRowBox.tsx  |  9 +++---
 4 files changed, 53 insertions(+), 15 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 365af66b7..4908d2952 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -227,7 +227,7 @@ export class DocumentOptions {
     _header_pointerEvents?: PEVt = new PEInfo('types of events the header of a custom text document can consume');
     _lockedPosition?: BOOLt = new BoolInfo("lock the x,y coordinates of the document so that it can't be dragged");
     _lockedTransform?: BOOLt = new BoolInfo('lock the freeform_panx,freeform_pany and scale parameters of the document so that it be panned/zoomed');
-    _childrenSharedWithSchema?: BOOLt = new BoolInfo("whether this document's children are displayed in its parent schema view");
+    _childrenSharedWithSchema?: BOOLt = new BoolInfo("whether this document's children are displayed in its parent schema view", false);
 
     dataViz_title?: string;
     dataViz_line?: string;
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index a2f88eb80..f501993b5 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1,7 +1,7 @@
 /* eslint-disable no-restricted-syntax */
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { IconButton, Popup, PopupTrigger, Size, Type } from 'browndash-components';
-import { ObservableMap, action, autorun, computed, makeObservable, observable, observe, runInAction } from 'mobx';
+import { ObservableMap, action, autorun, computed, makeObservable, observable, observe, override, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../ClientUtils';
@@ -65,6 +65,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     constructor(props: any) {
         super(props);
         makeObservable(this);
+        this.importAddedDocs();
     }
 
     static _rowHeight: number = 50;
@@ -106,7 +107,7 @@ export class CollectionSchemaView extends CollectionSubView() {
 
     @computed get _selectedDocs() {
         // get all selected documents then filter out any whose parent is not this schema document
-        const selected = DocumentView.SelectedDocs().filter(doc => this.childDocs.includes(doc));
+        const selected = DocumentView.SelectedDocs().filter(doc => this._docs.includes(doc));
         if (!selected.length) {
             // if no schema doc is directly selected, test if a child of a schema doc is selected (such as in the preview window)
             const childOfSchemaDoc = DocumentView.SelectedDocs().find(sel => DocumentView.getContextPath(sel, true).includes(this.Document));
@@ -197,6 +198,22 @@ export class CollectionSchemaView extends CollectionSubView() {
     // ViewBoxInterface overrides
     override isUnstyledView = returnTrue; // used by style provider : turns off  opacity, animation effects, scaling
 
+    importAddedDocs = () => {
+        const collections = this.childDocs.filter((doc: Doc) => doc.type === 'collection');
+        collections.forEach((doc: Doc) => {
+            const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]);
+            doc._childrenSharedWithSchema && this.addDocsFromOtherCollection(childDocs);
+        });
+    }
+
+    removeDoc = (doc: Doc) => {
+        console.log('called')
+        this.removeDocument(doc);
+        if (doc instanceof Doc) {
+            console.log('doc is doc')
+            this._docs = this._docs.filter(d => d !== doc)};
+    }
+
     rowIndex = (doc: Doc) => this.displayedDocs.docs.indexOf(doc);
 
     @action
@@ -256,13 +273,17 @@ export class CollectionSchemaView extends CollectionSubView() {
                     }
                     break;
                 case 'Backspace': {
-                    undoable(() => this.removeDocument(this._selectedDocs), 'delete schema row');
+                    undoable(() => {this._selectedDocs.forEach(d => this._docs.includes(d) && this.removeDoc(d));}, 'delete schema row');
                     break;
                 }
                 case 'Escape': {
                     this.deselectAllCells();
                     break;
                 }
+                case 'P': {
+                    this.importAddedDocs();
+                    break;
+                }
                 default:
             }
         }
@@ -635,11 +656,12 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     addDocsFromOtherCollection = (docs: Doc[]) => {
-        docs.forEach((doc: Doc) => {!this.displayedDocsFunc().includes(doc) && this._lentDocs.push(doc)});
+        docs.forEach((doc: Doc) => !this.displayedDocsFunc().includes(doc) && this._lentDocs.push(doc));
         this._docs = this.childDocs.slice().concat(this._lentDocs);
     }
+
     removeDocsFromOtherCollection = (docs: Doc[]) => {
-        this._lentDocs.filter((doc: Doc) => !docs.includes(doc));
+        this._lentDocs = this._lentDocs.filter((doc: Doc) => !docs.includes(doc));
         this._docs = this.childDocs.slice().concat(this._lentDocs);
     }
 
@@ -1032,7 +1054,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         return { docs };
     }
 
-    @action
+    @action 
     sortDocs = (docs: Doc[], field: string, desc: boolean) => {
         docs = docs.sort((docA, docB) => {
             // this sorts the documents based on the selected field.  returning -1 for a before b, 0 for a = b, 1 for a > b
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index dd4a13776..dbbf76ea7 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -22,6 +22,7 @@ import { SnappingManager } from '../../../util/SnappingManager';
 import { undoable } from '../../../util/UndoManager';
 import { FInfo } from '../../../documents/Documents';
 import { ColumnType } from '../../../../fields/SchemaHeaderField';
+import { IconButton, Size } from 'browndash-components';
 
 export interface SchemaColumnHeaderProps {
     Document: Doc;
@@ -174,10 +175,26 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
                     <div>{this.editableView}</div>
 
                     <div className="schema-header-menu">
-                        <div className="schema-header-button" onPointerDown={e => this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)}>
-                            <FontAwesomeIcon icon="ellipsis-h" />
+                        <div className="schema-header-button">
+                            <IconButton
+                            icon={ <FontAwesomeIcon icon="caret-down" size='lg'/>}
+                            size={Size.XSMALL}
+                            color={'black'}
+                            onPointerDown={e =>
+                                setupMoveUpEvents(
+                                    this,
+                                    e,
+                                    returnFalse,
+                                    emptyFunction,
+                                    undoable(clickEv => {
+                                        clickEv.stopPropagation();
+                                        this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)
+                                    }, 'open column menu')
+                                )
+                            }
+                        />
                         </div>
-                    </div>
+                    </div>  
                 </div>
         );
     }
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 665704de1..cdd47f644 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -60,7 +60,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         ContextMenu.Instance.clearItems();
         ContextMenu.Instance.addItem({
             description: `Close doc`,
-            event: () => this._props.removeDocument?.(this.Document),
+            event: () => this.schemaView.removeDoc(this.Document),
             icon: 'minus',
         });
         ContextMenu.Instance.addItem({
@@ -74,13 +74,12 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
             icon: 'magnifying-glass',
         });
         const childDocs = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)])
-        if (this.Document['type'] === 'collection' && childDocs.length) {
+        if (this.Document.type === 'collection' && childDocs.length) {
                 ContextMenu.Instance.addItem({
                 description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema',
                 event: () => {
                     this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; 
-                    this.Document._childrenSharedWithSchema ? 
-                    this.schemaView.addDocsFromOtherCollection(childDocs) : this.schemaView.removeDocsFromOtherCollection(childDocs);
+                    this.Document._childrenSharedWithSchema ? this.schemaView.addDocsFromOtherCollection(childDocs) : this.schemaView.removeDocsFromOtherCollection(childDocs);
                 },
                 icon: this.Document._childrenSharedWithSchema ? 'minus' : 'plus',
             });
@@ -115,7 +114,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                     }}>
                     <IconButton
                         tooltip="Open actions menu"
-                        icon={ <FontAwesomeIcon icon="list" size='lg'/>}
+                        icon={ <FontAwesomeIcon icon="caret-right" size='lg'/>}
                         size={Size.XSMALL}
                         color={'black'}
                         onPointerDown={e =>
-- 
cgit v1.2.3-70-g09d2


From 4b604b5118a1aac89d977c832c81495ec2c9aa19 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Mon, 10 Jun 2024 12:56:51 -0400
Subject: lock row editing

---
 src/client/documents/Documents.ts                  |  1 +
 src/client/views/EditableView.tsx                  |  2 ++
 .../collectionSchema/CollectionSchemaView.tsx      | 11 ++------
 .../collectionSchema/SchemaColumnHeader.tsx        |  1 +
 .../collections/collectionSchema/SchemaRowBox.tsx  | 15 ++++++++--
 .../collectionSchema/SchemaTableCell.tsx           | 33 ++++++++++++----------
 6 files changed, 37 insertions(+), 26 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 4908d2952..dabbf9591 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -228,6 +228,7 @@ export class DocumentOptions {
     _lockedPosition?: BOOLt = new BoolInfo("lock the x,y coordinates of the document so that it can't be dragged");
     _lockedTransform?: BOOLt = new BoolInfo('lock the freeform_panx,freeform_pany and scale parameters of the document so that it be panned/zoomed');
     _childrenSharedWithSchema?: BOOLt = new BoolInfo("whether this document's children are displayed in its parent schema view", false);
+    _lockedSchemaEditing?: BOOLt = new BoolInfo("", false);
 
     dataViz_title?: string;
     dataViz_line?: string;
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 1652e6cd7..c05812e1a 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -57,6 +57,7 @@ export interface EditableProps {
     wrap?: string; // nowrap, pre-wrap, etc
 
     schemaHeader?: boolean;
+    onClick?: () => void;
     updateAlt?: (newAlt: string) => void;
     updateSearch?: (value: string) => void;
 }
@@ -187,6 +188,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
 
     @action
     onClick = (e?: React.MouseEvent) => {
+        this._props.onClick && this._props.onClick();
         if (this._props.editing !== false) {
             e?.nativeEvent.stopPropagation();
             if (this._ref.current && this._props.showMenuOnLoad) {
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 7302a7c22..48287c3ec 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -208,7 +208,7 @@ export class CollectionSchemaView extends CollectionSubView() {
 
     removeDoc = (doc: Doc) => {
         this.removeDocument(doc);
-        this._docs = this._docs.filter(d => d !== doc);
+        this._docs = this._docs.filter(d => d !== doc)
     }
 
     rowIndex = (doc: Doc) => this.displayedDocs.docs.indexOf(doc);
@@ -739,13 +739,8 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     setCellValues = (key: string, value: string) => {
-        const selectedDocs: Doc[] = [];
-        this.childDocs.forEach(doc => {
-            const isSelected = this._selectedCells && !(this._selectedCells?.filter(d => d === doc).length === 0);
-            isSelected && selectedDocs.push(doc); 
-        });
-        if (selectedDocs.length === 1) this.childDocs.forEach(doc => Doc.SetField(doc, key, value)); // if only one cell selected, fill all
-        else selectedDocs.forEach(doc => Doc.SetField(doc, key, value)); // else only fill selected cells
+        if (this._selectedCells.length === 1) this.childDocs.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); // if only one cell selected, fill all
+        else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); // else only fill selected cells
         return true;
     };
 
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index dbbf76ea7..3719840ff 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -126,6 +126,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
                 oneLine={true}
                 allowCRs={false}
                 contents={undefined}
+                onClick={this.openKeyDropdown}
                 fieldContents={fieldProps}
                 editing={undefined}  
                 placeholder={'Add key'}
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index cdd47f644..58964d9fb 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -64,9 +64,9 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
             icon: 'minus',
         });
         ContextMenu.Instance.addItem({
-            description: this.Document._lockedPosition ? 'Unlock doc interactions' : 'Lock doc interactions',
-            event: () => Doc.toggleLockedPosition(this.Document),
-            icon: this.Document._lockedPosition ? 'lock-open' : 'lock',
+            description: this.Document._lockedSchemaEditing ? 'Unlock field editing' : 'Lock field editing',
+            event: () => this.Document._lockedSchemaEditing = !this.Document._lockedSchemaEditing,
+            icon: this.Document._lockedSchemaEditing ? 'lock-open' : 'lock',
         });
         ContextMenu.Instance.addItem({
             description: 'Open preview',
@@ -87,6 +87,14 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         ContextMenu.Instance.displayMenu(x, y, undefined, false);
     }
 
+    get menuBackgroundColor(){
+        if (this.Document._lockedSchemaEditing){
+            if (this._props.isSelected()) return '#B0D1E7'
+            else return '#F5F5F5'
+        }   
+        return ''
+    }
+
     cleanupField = (field: string) => this.schemaView.cleanupComputedField(field)
     setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY);
     selectedCol = () => this.schemaView._selectedCol;
@@ -111,6 +119,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                     style={{
                         width: CollectionSchemaView._rowMenuWidth,
                         pointerEvents: !this._props.isContentActive() ? 'none' : undefined,
+                        backgroundColor: this.menuBackgroundColor
                     }}>
                     <IconButton
                         tooltip="Open actions menu"
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index dc060218c..49ec70b74 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -76,8 +76,20 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         makeObservable(this);
     }
 
-    get defaultKey(){
-        return SchemaColumnHeader.isDefaultField(this._props.fieldKey)
+    get isDefault(){
+        return SchemaColumnHeader.isDefaultField(this._props.fieldKey);
+    }
+
+    get lockedInteraction(){
+        return (this.isDefault || this._props.Document._lockedSchemaEditing);
+    }
+
+    get backgroundColor(){
+        if (this.lockedInteraction){
+            if (this._props.rowSelected()) return '#B0D1E7'
+            else return '#F5F5F5'
+        }   
+        return ''
     }
 
     static addFieldDoc = (docs: Doc | Doc[] /* , where: OpenWhere */) => {
@@ -89,9 +101,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         let protoCount = 0;
         let doc: Doc | undefined = Document;
         while (doc) {
-            if (Object.keys(doc).includes(fieldKey.replace(/^_/, ''))) {
-                break;
-            }
+            if (Object.keys(doc).includes(fieldKey.replace(/^_/, ''))) break; 
             protoCount++;
             doc = DocCast(doc.proto);
         }
@@ -130,6 +140,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
     @computed get defaultCellContent() {
         const { color, textDecoration, fieldProps, pointerEvents } = SchemaTableCell.renderProps(this._props);
 
+
         return (
             <div
                 className="schemacell-edit-wrapper"
@@ -137,7 +148,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                     color,
                     textDecoration,
                     width: '100%',
-                    pointerEvents,
+                    pointerEvents: this.lockedInteraction ? 'none' : pointerEvents,
                 }}>
                 <EditableView
                     ref={r => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)}
@@ -190,14 +201,6 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         }
     }
 
-    get backgroundColor(){
-        if (this.defaultKey){
-            if (this._props.rowSelected()) return '#B0D1E7'
-            else return '#F5F5F5'
-        }   
-        return ''
-    }
-
     render() {
         return (
             <div
@@ -218,7 +221,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                 width: this._props.columnWidth() || undefined, 
                 border: selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined,
                 backgroundColor: this.backgroundColor}}>
-                {this.defaultKey ? '' : this.content}
+                {this.isDefault ? '' : this.content}
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From 03f9fd4beb2bd3efa8f88c71bdbaf52dbec82e66 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Mon, 10 Jun 2024 14:56:42 -0400
Subject: sub-collection doc adding refactor complete except for small bug

---
 .../collectionSchema/CollectionSchemaView.tsx      | 51 +++++++++---------
 .../collectionSchema/SchemaColumnHeader.tsx        | 60 +++++++++++++++-------
 .../collections/collectionSchema/SchemaRowBox.tsx  |  1 -
 3 files changed, 65 insertions(+), 47 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 48287c3ec..1952f59f5 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -65,7 +65,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     constructor(props: any) {
         super(props);
         makeObservable(this);
-        this.importAddedDocs();
     }
 
     static _rowHeight: number = 50;
@@ -97,7 +96,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     @observable _colBeingDragged: boolean = false;
     @observable _colKeysFiltered: boolean = false;
     @observable _cellTags: ObservableMap = new ObservableMap<Doc, Array<string>>();
-    @observable _lentDocs: Doc[] = [];
     @observable _docs: Doc[] = this.childDocs;
 
     // target HTMLelement portal for showing a popup menu to edit cell values.
@@ -150,7 +148,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     }
 
     @computed get rowHeights() {
-        return this.childDocs.concat(this._lentDocs).map(() => this.rowHeightFunc());
+        return this.docs.map(() => this.rowHeightFunc());
     }
 
     @computed get displayColumnWidths() {
@@ -198,14 +196,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     // ViewBoxInterface overrides
     override isUnstyledView = returnTrue; // used by style provider : turns off  opacity, animation effects, scaling
 
-    importAddedDocs = () => {
-        const collections = this.childDocs.filter((doc: Doc) => doc.type === 'collection');
-        collections.forEach((doc: Doc) => {
-            const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]);
-            doc._childrenSharedWithSchema && this.addDocsFromOtherCollection(childDocs);
-        });
-    }
-
     removeDoc = (doc: Doc) => {
         this.removeDocument(doc);
         this._docs = this._docs.filter(d => d !== doc)
@@ -278,7 +268,6 @@ export class CollectionSchemaView extends CollectionSubView() {
                     break;
                 }
                 case 'P': {
-                    this.importAddedDocs();
                     break;
                 }
                 default:
@@ -651,16 +640,6 @@ export class CollectionSchemaView extends CollectionSubView() {
         return undefined;
     };
 
-    addDocsFromOtherCollection = (docs: Doc[]) => {
-        docs.forEach((doc: Doc) => !this.displayedDocsFunc().includes(doc) && this._lentDocs.push(doc));
-        this._docs = this.childDocs.slice().concat(this._lentDocs);
-    }
-
-    removeDocsFromOtherCollection = (docs: Doc[]) => {
-        this._lentDocs = this._lentDocs.filter((doc: Doc) => !docs.includes(doc));
-        this._docs = this.childDocs.slice().concat(this._lentDocs);
-    }
-
     @computed get fieldDefaultInput() {
         switch (this._newFieldType) {
             case ColumnType.Number:
@@ -739,7 +718,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     setCellValues = (key: string, value: string) => {
-        if (this._selectedCells.length === 1) this.childDocs.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); // if only one cell selected, fill all
+        if (this._selectedCells.length === 1) this.childDocs.forEach(doc => !doc._lockedSchemaEditing &&Doc.SetField(doc, key, value)); // if only one cell selected, fill all
         else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); // else only fill selected cells
         return true;
     };
@@ -1038,16 +1017,36 @@ export class CollectionSchemaView extends CollectionSubView() {
         }
     };
 
+    displayedSubCollectionDocs = (doc: Doc) => {
+        const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]);
+        const displayedCollections = childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema);
+        let toReturn: Doc[] = [...childDocs];
+        displayedCollections.forEach(d => toReturn = toReturn.concat(this.displayedSubCollectionDocs(d)));
+        return toReturn;
+    }
+    
+    @computed get docs() {
+        let docsFromChildren: Doc[] = [];
+        const displayedCollections = this.childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema);
+        displayedCollections.forEach(d => {
+            let docsNotAlreadyDisplayed = this.displayedSubCollectionDocs(d).filter(dc => !this._docs.includes(dc));
+            docsFromChildren = docsFromChildren.concat(docsNotAlreadyDisplayed);
+        });
+        let docs = this._docs.concat(docsFromChildren);
+        return docs;
+    }
+    
     @computed get displayedDocs() {
         const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : [];
-        const docs = this._docs.filter(d => !draggedDocs.includes(d));
+        let docs = [...this.docs];
+        docs = docs.filter(d => !draggedDocs.includes(d));
         docs.splice(this.rowDropIndex, 0, ...draggedDocs);
         return { docs };
     }
 
     @action 
     sortDocs = (docs: Doc[], field: string, desc: boolean) => {
-        docs = docs.sort((docA, docB) => {
+        this._docs = docs.sort((docA, docB) => {
             // this sorts the documents based on the selected field.  returning -1 for a before b, 0 for a = b, 1 for a > b
             const aStr = Field.toString(docA[field] as FieldType);
             const bStr = Field.toString(docB[field] as FieldType);
@@ -1115,8 +1114,6 @@ export class CollectionSchemaView extends CollectionSubView() {
                                 columnIndex={index}
                                 columnKeys={this.columnKeys}
                                 columnWidths={this.displayColumnWidths}
-                                sortField={this.sortField}
-                                sortDesc={this.sortDesc}
                                 setSort={this.setColumnSort}
                                 rowHeight={this.rowHeightFunc}
                                 removeColumn={this.removeColumn}
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 3719840ff..0da186f81 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -30,8 +30,6 @@ export interface SchemaColumnHeaderProps {
     columnKeys: string[];
     columnWidths: number[];
     columnIndex: number;
-    sortField: string;
-    sortDesc: boolean;
     schemaView: CollectionSchemaView;
     keysDropdown: React.JSX.Element;
     //cleanupField: (s: string) => string;
@@ -158,6 +156,46 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
         return isDefault;
     }
 
+    get headerButton(){
+        const toRender = SchemaColumnHeader.isDefaultField(this.fieldKey) ? 
+        (<IconButton
+            icon={ <FontAwesomeIcon icon="trash" size='sm'/>}
+            size={Size.XSMALL}
+            color={'black'}
+            onPointerDown={e =>
+                setupMoveUpEvents(
+                    this,
+                    e,
+                    returnFalse,
+                    emptyFunction,
+                    undoable(clickEv => {
+                        clickEv.stopPropagation();
+                        this._props.schemaView.removeColumn(this._props.columnIndex);
+                    }, 'open column menu')
+                )
+            }
+        />)
+        : (<IconButton
+            icon={ <FontAwesomeIcon icon="caret-down" size='lg'/>}
+            size={Size.XSMALL}
+            color={'black'}
+            onPointerDown={e =>
+                setupMoveUpEvents(
+                    this,
+                    e,
+                    returnFalse,
+                    emptyFunction,
+                    undoable(clickEv => {
+                        clickEv.stopPropagation();
+                        this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)
+                    }, 'open column menu')
+                )
+            }
+        />)
+
+        return toRender;
+    }
+
     render() {
         return (
                 <div
@@ -177,23 +215,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
 
                     <div className="schema-header-menu">
                         <div className="schema-header-button">
-                            <IconButton
-                            icon={ <FontAwesomeIcon icon="caret-down" size='lg'/>}
-                            size={Size.XSMALL}
-                            color={'black'}
-                            onPointerDown={e =>
-                                setupMoveUpEvents(
-                                    this,
-                                    e,
-                                    returnFalse,
-                                    emptyFunction,
-                                    undoable(clickEv => {
-                                        clickEv.stopPropagation();
-                                        this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)
-                                    }, 'open column menu')
-                                )
-                            }
-                        />
+                            {this.headerButton}
                         </div>
                     </div>  
                 </div>
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 58964d9fb..a0d3144ce 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -79,7 +79,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                 description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema',
                 event: () => {
                     this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; 
-                    this.Document._childrenSharedWithSchema ? this.schemaView.addDocsFromOtherCollection(childDocs) : this.schemaView.removeDocsFromOtherCollection(childDocs);
                 },
                 icon: this.Document._childrenSharedWithSchema ? 'minus' : 'plus',
             });
-- 
cgit v1.2.3-70-g09d2


From c2a2b8c119c44b167310485cede0920f313cd40a Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Tue, 11 Jun 2024 01:56:17 -0400
Subject: rowmenu info icons

---
 src/client/views/MainView.tsx                      |  1 +
 .../collectionSchema/CollectionSchemaView.scss     | 17 ++++++++++++++---
 .../collectionSchema/CollectionSchemaView.tsx      | 22 ++++++++++------------
 .../collections/collectionSchema/SchemaRowBox.tsx  | 13 ++++++++++++-
 4 files changed, 37 insertions(+), 16 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 8dc2ce98a..5b9ddbb88 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -278,6 +278,7 @@ export class MainView extends ObservableReactComponent<{}> {
 
         library.add(
             ...[
+                fa.faGift,
                 fa.faLockOpen,
                 fa.faSort,
                 fa.faArrowUpZA,
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
index ceffc7e44..d1f1e3a13 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
@@ -259,9 +259,6 @@
         flex-direction: row;
         min-width: 50px;
         justify-content: center;
-        .iconButton-container {
-            min-width: unset !important;
-        }
     }
 
     .row-cells {
@@ -269,6 +266,20 @@
         flex-direction: row;
         justify-content: flex-end;
     }
+
+    .row-menu-infos {
+        position: absolute;
+        top: 3;
+        left: 3; 
+        z-index: 1;
+        display: flex;
+        justify-content: flex-end;
+        align-items: center;
+
+        .row-infos-icon {
+            padding-right: 2px;
+        }
+    }
 }
 
 .schema-row-button,
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index dc29e7413..4abbc7f51 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -201,7 +201,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         this._docs = this._docs.filter(d => d !== doc)
     }
 
-    rowIndex = (doc: Doc) => this.displayedDocs.docs.indexOf(doc);
+    rowIndex = (doc: Doc) => this.draggedSpliceDocs.docs.indexOf(doc);
 
     @action
     onKeyDown = (e: KeyboardEvent) => {
@@ -211,9 +211,9 @@ export class CollectionSchemaView extends CollectionSubView() {
                     {
                         const lastDoc = this._selectedDocs.lastElement();
                         const lastIndex = this.rowIndex(lastDoc);
-                        const curDoc = this.displayedDocs.docs[lastIndex];
+                        const curDoc = this.docs[lastIndex];
                         if (lastIndex >= 0 && lastIndex < this.childDocs.length - 1) {
-                            const newDoc = this.displayedDocs.docs[lastIndex + 1];
+                            const newDoc = this.docs[lastIndex + 1];
                             if (this._selectedDocs.includes(newDoc)) {
                                 DocumentView.DeselectView(DocumentView.getFirstDocumentView(curDoc));
                                 this.deselectCell(curDoc);
@@ -230,9 +230,9 @@ export class CollectionSchemaView extends CollectionSubView() {
                     {
                         const firstDoc = this._selectedDocs.lastElement();
                         const firstIndex = this.rowIndex(firstDoc);
-                        const curDoc = this.displayedDocs.docs[firstIndex];
+                        const curDoc = this.docs[firstIndex];
                         if (firstIndex > 0 && firstIndex < this.childDocs.length) {
-                            const newDoc = this.displayedDocs.docs[firstIndex - 1];
+                            const newDoc = this.docs[firstIndex - 1];
                             if (this._selectedDocs.includes(newDoc)) {
                                 DocumentView.DeselectView(DocumentView.getFirstDocumentView(curDoc));
                                 this.deselectCell(curDoc);
@@ -514,7 +514,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         const startRow = Math.min(lastSelectedRow, index);
         const endRow = Math.max(lastSelectedRow, index);
         for (let i = startRow; i <= endRow; i++) {
-            const currDoc = this.displayedDocs.docs[i];
+            const currDoc = this.docs[i];
             if (!this._selectedDocs.includes(currDoc)) {
                 this.selectCell(currDoc, this._selectedCol, false, true);
             }
@@ -555,8 +555,6 @@ export class CollectionSchemaView extends CollectionSubView() {
         this._lowestSelectedIndex = -1;
     };
 
-    sortedSelectedDocs = () => this.displayedDocs.docs.filter(doc => this._selectedDocs.includes(doc));
-
     @computed
     get rowDropIndex() {
         const mouseY = this.ScreenToLocalBoxXf().transformPoint(this._mouseCoordinates.x, this._mouseCoordinates.y)[1];
@@ -587,7 +585,7 @@ export class CollectionSchemaView extends CollectionSubView() {
 
         const draggedDocs = de.complete.docDragData?.draggedDocuments;
         if (draggedDocs && super.onInternalDrop(e, de) && !this.sortField) {
-            const docs = this.displayedDocs.docs.slice();
+            const docs = this.draggedSpliceDocs.docs.slice();
             this._docs = docs;
             this.clearSelection();
             draggedDocs.forEach(doc => {
@@ -719,7 +717,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     setCellValues = (key: string, value: string) => {
-        if (this._selectedCells.length === 1) this.childDocs.forEach(doc => !doc._lockedSchemaEditing &&Doc.SetField(doc, key, value)); // if only one cell selected, fill all
+        if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing &&Doc.SetField(doc, key, value)); // if only one cell selected, fill all
         else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); // else only fill selected cells
         return true;
     };
@@ -1037,7 +1035,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         return docs;
     }
     
-    @computed get displayedDocs() {
+    @computed get draggedSpliceDocs() {
         const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : [];
         let docs = [...this.docs];
         docs = docs.filter(d => !draggedDocs.includes(d));
@@ -1064,7 +1062,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0);
     previewWidthFunc = () => this.previewWidth;
     onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
-    displayedDocsFunc = () => this.displayedDocs.docs;
+    displayedDocsFunc = () => this.draggedSpliceDocs.docs;
     _oldWheel: any;
     render() {
         return (
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index a0d3144ce..98a16deea 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -7,7 +7,7 @@ import { CgClose, CgLock, CgLockUnlock, CgMenu } from 'react-icons/cg';
 import { FaExternalLinkAlt } from 'react-icons/fa';
 import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils';
 import { emptyFunction } from '../../../../Utils';
-import { Doc, DocListCast } from '../../../../fields/Doc';
+import { Doc, DocListCast, FieldResult } from '../../../../fields/Doc';
 import { BoolCast } from '../../../../fields/Types';
 import { Transform } from '../../../util/Transform';
 import { undoable } from '../../../util/UndoManager';
@@ -21,6 +21,7 @@ import { SchemaTableCell } from './SchemaTableCell';
 import { ContextMenu } from '../../ContextMenu';
 import { CollectionFreeFormView } from '../collectionFreeForm';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { IconProp } from '@fortawesome/fontawesome-svg-core';
 
 interface SchemaRowBoxProps extends FieldViewProps {
     rowIndex: number;
@@ -94,6 +95,13 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         return ''
     }
 
+    get menuInfos() {
+        const infos: Array<IconProp> = [];
+        if (this.Document._lockedSchemaEditing) infos.push('lock');
+        if (this.Document._childrenSharedWithSchema) infos.push('star');
+        return infos;
+    }
+
     cleanupField = (field: string) => this.schemaView.cleanupComputedField(field)
     setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY);
     selectedCol = () => this.schemaView._selectedCol;
@@ -113,6 +121,9 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                     row && this.schemaView?.addRowRef?.(this.Document, row);
                     this._ref = row;
                 }}>
+                <div className="row-menu-infos">
+                    {this.menuInfos.map(icn => <FontAwesomeIcon className="row-infos-icon" icon={icn} size='2xs' />)}
+                </div>
                 <div
                     className="row-menu"
                     style={{
-- 
cgit v1.2.3-70-g09d2


From 571220cb349644efc149b8e13d000a37366db664 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Wed, 12 Jun 2024 02:50:19 -0400
Subject: fixed col drag highlight and cleaned up multi-select highlight

---
 .../collectionSchema/CollectionSchemaView.tsx      | 14 +-------
 .../collections/collectionSchema/SchemaRowBox.tsx  | 23 ++++++++----
 .../collectionSchema/SchemaTableCell.tsx           | 42 +++++++++++++++++++---
 3 files changed, 54 insertions(+), 25 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 033bc74d2..25a1b4819 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -325,17 +325,6 @@ export class CollectionSchemaView extends CollectionSubView() {
         });
     }
 
-    // parses a field from the "idToDoc(####)" format to DocumentId (d#) format for readability
-    cleanupComputedField = (field: string) => {
-        const idPattern = /idToDoc\((.*?)\)/g;
-        let modField = field.slice();
-        let matches;
-        let results = new Map<string, string>();
-        while ((matches = idPattern.exec(field)) !== null) {results.set(matches[0], matches[1].replace(/"/g, '')); }
-        results.forEach((id, funcId) => {modField = modField.replace(funcId, 'd' + (DocumentView.getDocViewIndex(IdToDoc(id))).toString());})
-        return modField;
-    }
-
     @undoBatch
     removeColumn = (index: number) => {
         if (this.columnKeys.length === 1) return;
@@ -480,7 +469,7 @@ export class CollectionSchemaView extends CollectionSubView() {
             const edgeStyle = i === index ? `solid 2px ${Colors.MEDIUM_BLUE}` : '';
             const cellEles = [
                 colRef,
-                ...this.childDocs 
+                ...this.docs 
                     .filter(doc => i !== this._selectedCol || !this._selectedDocs.includes(doc))
                     .map(doc => this._rowEles.get(doc).children[1].children[i]),
             ];
@@ -534,7 +523,6 @@ export class CollectionSchemaView extends CollectionSubView() {
         if (!shiftKey && !ctrlKey) this.clearSelection();
         !this._selectedCells && (this._selectedCells = []);
         !shiftKey && this._selectedCells.push(doc);
-        this._selectedCells.forEach(d => console.log(d.title))
         const index = this.rowIndex(doc);
 
         if (!this) return;
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 98a16deea..a8affb0d9 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -87,7 +87,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         ContextMenu.Instance.displayMenu(x, y, undefined, false);
     }
 
-    get menuBackgroundColor(){
+    @computed get menuBackgroundColor(){
         if (this.Document._lockedSchemaEditing){
             if (this._props.isSelected()) return '#B0D1E7'
             else return '#F5F5F5'
@@ -95,14 +95,22 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         return ''
     }
 
-    get menuInfos() {
+    @computed get menuInfos() {
         const infos: Array<IconProp> = [];
         if (this.Document._lockedSchemaEditing) infos.push('lock');
         if (this.Document._childrenSharedWithSchema) infos.push('star');
         return infos;
     }
 
-    cleanupField = (field: string) => this.schemaView.cleanupComputedField(field)
+    @computed get isolatedSelection() {
+        const toReturn: [boolean, boolean] = [true, true];
+        const selectedBelow: boolean = this.schemaView?._selectedDocs.includes(this.schemaView.draggedSpliceDocs.docs[this.rowIndex + 1]);
+        const selectedAbove: boolean = this.schemaView?._selectedDocs.includes(this.schemaView.draggedSpliceDocs.docs[this.rowIndex - 1]);
+        toReturn[0] = selectedAbove;
+        toReturn[1] = selectedBelow;
+        return toReturn;
+    }
+
     setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY);
     selectedCol = () => this.schemaView._selectedCol;
     getFinfo = computedFn((fieldKey: string) => this.schemaView?.fieldInfos.get(fieldKey));
@@ -111,6 +119,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
     selectedCells = () => this.schemaView?._selectedDocs;
     setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false;
     columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
+    computeRowIndex = () => this.schemaView?.rowIndex(this.Document);
     render() {
         return (
             <div
@@ -121,9 +130,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                     row && this.schemaView?.addRowRef?.(this.Document, row);
                     this._ref = row;
                 }}>
-                <div className="row-menu-infos">
-                    {this.menuInfos.map(icn => <FontAwesomeIcon className="row-infos-icon" icon={icn} size='2xs' />)}
-                </div>
                 <div
                     className="row-menu"
                     style={{
@@ -149,10 +155,14 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                             )
                         }
                     />
+                <div className="row-menu-infos">
+                    {this.menuInfos.map(icn => <FontAwesomeIcon className="row-infos-icon" icon={icn} size='2xs' />)}
+                </div>
                 </div>
                 <div className="row-cells">
                     {this.schemaView?.columnKeys?.map((key, index) => (
                         <SchemaTableCell
+                            isolatedSelection={this.isolatedSelection}
                             key={key}
                             rowSelected={this._props.isSelected}
                             Document={this.Document}
@@ -170,7 +180,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                             setColumnValues={this.setColumnValues}
                             oneLine={BoolCast(this.schemaDoc?._singleLine)}
                             menuTarget={this.schemaView.MenuTarget}
-                            cleanupField={this.cleanupField}
                             transform={() => {
                                 const ind = index === this.schemaView.columnKeys.length - 1 ? this.schemaView.columnKeys.length - 3 : index;
                                 const x = this.schemaView?.displayColumnWidths.reduce((p, c, i) => (i <= ind ? p + c : p), 0);
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 791465741..c8bd48019 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -13,7 +13,7 @@ import Select from 'react-select';
 import { ClientUtils, StopEvent, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero } from '../../../../ClientUtils';
 import { emptyFunction } from '../../../../Utils';
 import { DateField } from '../../../../fields/DateField';
-import { Doc, DocListCast, Field } from '../../../../fields/Doc';
+import { Doc, DocListCast, Field, IdToDoc } from '../../../../fields/Doc';
 import { RichTextField } from '../../../../fields/RichTextField';
 import { ColumnType } from '../../../../fields/SchemaHeaderField';
 import { BoolCast, Cast, DateCast, DocCast, FieldValue, StrCast, toList } from '../../../../fields/Types';
@@ -33,6 +33,7 @@ import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
 import { CollectionSchemaView, FInfotoColType } from './CollectionSchemaView';
 import './CollectionSchemaView.scss';
 import { SchemaColumnHeader } from './SchemaColumnHeader';
+import { ContextMenu } from '../../ContextMenu';
 
 export interface SchemaTableCellProps {
     Document: Doc;
@@ -57,8 +58,8 @@ export interface SchemaTableCellProps {
     transform: () => Transform;
     autoFocus?: boolean; // whether to set focus on creation, othwerise wait for a click
     rootSelected?: () => boolean;
-    cleanupField: (field: string) => string;
     rowSelected: () => boolean;
+    isolatedSelection: [boolean, boolean];
 }
 
 function selectedCell(props: SchemaTableCellProps) {
@@ -137,13 +138,32 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         return { color, textDecoration, fieldProps, cursor, pointerEvents };
     }
 
+    // openContextMenu = () => {
+    //     const cm = ContextMenu.Instance;
+    //     cm.clearItems();
+
+        
+    // }
+
+    // parses a field from the "idToDoc(####)" format to DocumentId (d#) format for readability
+    cleanupField = (field: string) => {
+        const idPattern = /idToDoc\((.*?)\)/g;
+        let modField = field.slice();
+        let matches;
+        let results = new Map<string, string>();
+        while ((matches = idPattern.exec(field)) !== null) {results.set(matches[0], matches[1].replace(/"/g, '')); }
+        results.forEach((id, funcId) => {modField = modField.replace(funcId, 'd' + (DocumentView.getDocViewIndex(IdToDoc(id))).toString());})
+        if (!modField) modField = '';
+        return modField;
+    }
+
     @computed get defaultCellContent() {
         const { color, textDecoration, fieldProps, pointerEvents } = SchemaTableCell.renderProps(this._props);
 
-
         return (
             <div
                 className="schemacell-edit-wrapper"
+                // onContextMenu={}
                 style={{
                     color,
                     textDecoration,
@@ -157,7 +177,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                     contents={undefined}
                     fieldContents={fieldProps}
                     editing={selectedCell(this._props) ? undefined : false}
-                    GetValue={() => this._props.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey))} //TODO: feed this into parser that handles idToDoc
+                    GetValue={() => this.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey))}
                     SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => {
                         if (shiftDown && enterKey) {
                             this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value);
@@ -201,6 +221,15 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         }
     }
 
+    @computed get borderColor() {
+        const sides: Array<string | undefined> = [];
+        sides[0] = selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // left
+        sides[1] = selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // right
+        sides[2] = (!this._props.isolatedSelection[0] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // top
+        sides[3] = (!this._props.isolatedSelection[1] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // bottom
+        return sides;
+    }
+
     render() {
         return (
             <div
@@ -220,7 +249,10 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                 style={{ padding: this._props.padding, 
                 maxWidth: this._props.maxWidth?.(), 
                 width: this._props.columnWidth() || undefined, 
-                border: selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined,
+                borderLeft: this.borderColor[0],
+                borderRight: this.borderColor[1],
+                borderTop: this.borderColor[2],
+                borderBottom: this.borderColor[3],
                 backgroundColor: this.backgroundColor}}>
                 {this.isDefault ? '' : this.content}
             </div>
-- 
cgit v1.2.3-70-g09d2


From 707a1a4cba9f0af9ee07b487eddf0f4ca85c8a78 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Wed, 12 Jun 2024 03:28:07 -0400
Subject: col menu icon now shows only on hover

---
 .../collections/collectionSchema/CollectionSchemaView.tsx  |  8 ++++----
 .../collections/collectionSchema/SchemaColumnHeader.tsx    | 14 +++++++++++---
 .../views/collections/collectionSchema/SchemaRowBox.tsx    |  5 +++--
 3 files changed, 18 insertions(+), 9 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 25a1b4819..affa70a62 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -209,7 +209,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         this._docs = this._docs.filter(d => d !== doc)
     }
 
-    rowIndex = (doc: Doc) => this.draggedSpliceDocs.docs.indexOf(doc);
+    rowIndex = (doc: Doc) => this.docsWithDrag.docs.indexOf(doc);
 
     @action
     onKeyDown = (e: KeyboardEvent) => {
@@ -581,7 +581,7 @@ export class CollectionSchemaView extends CollectionSubView() {
 
         const draggedDocs = de.complete.docDragData?.draggedDocuments;
         if (draggedDocs && super.onInternalDrop(e, de) && !this.sortField) {
-            const docs = this.draggedSpliceDocs.docs.slice();
+            const docs = this.docsWithDrag.docs.slice();
             this._docs = docs;
             this.clearSelection();
             draggedDocs.forEach(doc => {
@@ -1031,7 +1031,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         return docs;
     }
     
-    @computed get draggedSpliceDocs() {
+    @computed get docsWithDrag() {
         const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : [];
         let docs = [...this.docs];
         docs = docs.filter(d => !draggedDocs.includes(d));
@@ -1058,7 +1058,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0);
     previewWidthFunc = () => this.previewWidth;
     onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
-    displayedDocsFunc = () => this.draggedSpliceDocs.docs;
+    displayedDocsFunc = () => this.docsWithDrag.docs;
     _oldWheel: any;
     render() {
         return (
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 0da186f81..0fe0033d4 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -1,6 +1,6 @@
 /* eslint-disable react/no-unused-prop-types */
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable } from 'mobx';
+import { action, computed, makeObservable, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero, setupMoveUpEvents } from '../../../../ClientUtils';
@@ -51,7 +51,7 @@ export interface SchemaColumnHeaderProps {
 export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHeaderProps> {
 
     @observable _altTitle: string | undefined = undefined;
-    @observable _displayKeysDropdown: boolean = false;
+    @observable _showMenuIcon: boolean = false;
 
     @computed get fieldKey() {
         return this._props.columnKeys[this._props.columnIndex];
@@ -59,6 +59,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
 
     constructor(props: SchemaColumnHeaderProps){
         super(props);
+        makeObservable(this);
         this._props.schemaView.openColumnMenu(0, false)
     }
     
@@ -196,6 +197,11 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
         return toRender;
     }
 
+    @action handlePointerEnter = () => this._showMenuIcon = true;
+    @action handlePointerLeave = () => this._showMenuIcon = false;
+
+    @computed get displayButton() {return this._showMenuIcon;}
+
     render() {
         return (
                 <div
@@ -203,6 +209,8 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
                     style={{
                         width: this._props.columnWidths[this._props.columnIndex],
                     }}
+                    onPointerEnter={() => {this.handlePointerEnter()}}
+                    onPointerLeave={() => {this.handlePointerLeave()}}
                     onPointerDown={this.setupDrag}
                     ref={col => {
                         if (col) {
@@ -215,7 +223,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
 
                     <div className="schema-header-menu">
                         <div className="schema-header-button">
-                            {this.headerButton}
+                            {this.displayButton ? this.headerButton : null}
                         </div>
                     </div>  
                 </div>
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index a8affb0d9..107e29754 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -104,8 +104,9 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
 
     @computed get isolatedSelection() {
         const toReturn: [boolean, boolean] = [true, true];
-        const selectedBelow: boolean = this.schemaView?._selectedDocs.includes(this.schemaView.draggedSpliceDocs.docs[this.rowIndex + 1]);
-        const selectedAbove: boolean = this.schemaView?._selectedDocs.includes(this.schemaView.draggedSpliceDocs.docs[this.rowIndex - 1]);
+        const docs = this.schemaView.docsWithDrag.docs;
+        const selectedBelow: boolean = this.schemaView?._selectedDocs.includes(docs[this.rowIndex + 1]);
+        const selectedAbove: boolean = this.schemaView?._selectedDocs.includes(docs[this.rowIndex - 1]);
         toReturn[0] = selectedAbove;
         toReturn[1] = selectedBelow;
         return toReturn;
-- 
cgit v1.2.3-70-g09d2


From 60a4ccfe2ab6337c064da8a303336f1872f5e9a6 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Wed, 12 Jun 2024 21:16:17 -0400
Subject: cell value parser for highlighting cells used in equation works; need
 to implement actual VU

---
 src/client/views/EditableView.tsx                  | 16 ++++----
 .../collectionSchema/CollectionSchemaView.tsx      | 48 +++++++++++++++++++---
 .../collectionSchema/SchemaColumnHeader.tsx        |  6 ++-
 .../collections/collectionSchema/SchemaRowBox.tsx  |  2 +
 .../collectionSchema/SchemaTableCell.tsx           |  5 +++
 5 files changed, 63 insertions(+), 14 deletions(-)

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

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index c05812e1a..f8d6596d8 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -11,6 +11,7 @@ import { FieldView, FieldViewProps } from './nodes/FieldView';
 import { ObservableReactComponent } from './ObservableReactComponent';
 import { OverlayView } from './OverlayView';
 import { Padding } from 'browndash-components';
+import { SchemaFieldType } from './collections/collectionSchema/SchemaColumnHeader';
 
 export interface EditableProps {
     /**
@@ -56,7 +57,7 @@ export interface EditableProps {
     placeholder?: string;
     wrap?: string; // nowrap, pre-wrap, etc
 
-    schemaHeader?: boolean;
+    schemaFieldType?: SchemaFieldType;
     onClick?: () => void;
     updateAlt?: (newAlt: string) => void;
     updateSearch?: (value: string) => void;
@@ -71,19 +72,18 @@ export interface EditableProps {
 export class EditableView extends ObservableReactComponent<EditableProps> {
     private _ref = React.createRef<HTMLDivElement>();
     private _inputref: HTMLInputElement | HTMLTextAreaElement | null = null;
+    private _disposers: { [name: string]: IReactionDisposer } = {};
     _overlayDisposer?: () => void;
-    _editingDisposer?: IReactionDisposer;
+    _highlightsDisposer?: () => void;
     @observable _editing: boolean = false;
 
     constructor(props: EditableProps) {
         super(props);
         makeObservable(this);
-        this._editing = !!this._props.editing;
-        if (this._props.schemaHeader) this._editing = true;
     }
 
     componentDidMount(): void {
-        this._editingDisposer = reaction(
+        this._disposers.editing = reaction(
             () => this._editing,
             editing => {
                 if (editing) {
@@ -91,7 +91,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
                         if (this._inputref?.value.startsWith('=') || this._inputref?.value.startsWith(':=')) {
                             this._overlayDisposer?.();
                             this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
-                        }
+                        } 
                     });
                 } else {
                     this._overlayDisposer?.();
@@ -114,7 +114,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
 
     componentWillUnmount() {
         this._overlayDisposer?.();
-        this._editingDisposer?.();
+        this._disposers.editing?.();
         this._inputref?.value && this.finalizeEdit(this._inputref.value, false, true, false);
     }
 
@@ -287,7 +287,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
     staticDisplay = () => {
         let toDisplay;
         const gval = this._props.GetValue()?.replace(/\n/g, '\\r\\n');
-        if (this._props.schemaHeader){
+        if (this._props.schemaFieldType === SchemaFieldType.Header){
             toDisplay = <input className="editableView-input"
             value={gval}
             placeholder='Add key'
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index affa70a62..4d959e42c 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -39,6 +39,7 @@ import { listSpec } from '../../../../fields/Schema';
 import { GetEffectiveAcl } from '../../../../fields/util';
 import { ContextMenuProps } from '../../ContextMenuItem';
 import { truncate } from 'lodash';
+import { DocumentManager } from '../../../util/DocumentManager';
 
 const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore
 
@@ -481,6 +482,39 @@ export class CollectionSchemaView extends CollectionSubView() {
             cellEles.slice(-1)[0].style.borderBottom = edgeStyle;
         });
 
+    getCellElement = (doc: Doc, fieldKey: string) => {
+        const index = this.columnKeys.indexOf(fieldKey);
+        console.log(doc.title)
+        const cell = this._rowEles.get(doc).children[1].children[index];
+        return cell;
+    }
+
+    findCellRefs = (text: string) => {
+        const pattern = /(this|d(\d+))\.(\w+)/g;
+        interface Match { docRef: string; field: string; }
+
+        const matches: Match[] = [];
+        let match: RegExpExecArray | null;
+
+        while ((match = pattern.exec(text)) !== null) {
+            const docRef = match[1] === 'this' ? match[1] : match[2]; 
+        matches.push({ docRef, field: match[3] });
+        }
+
+        const cells: Array<any> = [];
+        matches.forEach((match: Match) => {
+            const {docRef, field} = match;
+            const doc = DocumentManager.Instance.DocumentViews[Number(docRef)].Document;
+            if (this.columnKeys.includes(field)) {cells.push(this.getCellElement(doc, field))}
+        })
+
+        console.log(cells);
+
+        return cells;
+    }
+
+
+
     @action
     addRowRef = (doc: Doc, ref: HTMLDivElement) => this._rowEles.set(doc, ref);
 
@@ -1012,22 +1046,26 @@ export class CollectionSchemaView extends CollectionSubView() {
         }
     };
 
-    displayedSubCollectionDocs = (doc: Doc) => {
+    subCollectionDocs = (doc: Doc, displayed: boolean) => {
         const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]);
-        const displayedCollections = childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema);
+        let collections: Array<Doc> = [];
+        if (displayed) collections = childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema);
+        else collections = childDocs.filter(d => d.type === 'collection' && !d._childrenSharedWithSchema);
         let toReturn: Doc[] = [...childDocs];
-        displayedCollections.forEach(d => toReturn = toReturn.concat(this.displayedSubCollectionDocs(d)));
+        collections.forEach(d => toReturn = toReturn.concat(this.subCollectionDocs(d, displayed)));
         return toReturn;
     }
-    
+
     @computed get docs() {
         let docsFromChildren: Doc[] = [];
+
         const displayedCollections = this.childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema);
         displayedCollections.forEach(d => {
-            let docsNotAlreadyDisplayed = this.displayedSubCollectionDocs(d).filter(dc => !this._docs.includes(dc));
+            let docsNotAlreadyDisplayed = this.subCollectionDocs(d, true).filter(dc => !this._docs.includes(dc));
             docsFromChildren = docsFromChildren.concat(docsNotAlreadyDisplayed);
         });
         let docs = this._docs.concat(docsFromChildren);
+
         return docs;
     }
     
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 0fe0033d4..f0debaec2 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -24,6 +24,10 @@ import { FInfo } from '../../../documents/Documents';
 import { ColumnType } from '../../../../fields/SchemaHeaderField';
 import { IconButton, Size } from 'browndash-components';
 
+export enum SchemaFieldType {
+    Header, Cell
+}
+
 export interface SchemaColumnHeaderProps {
     Document: Doc;
     autoFocus?: boolean;
@@ -131,7 +135,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
                 placeholder={'Add key'}
                 updateAlt={this.updateAlt} // alternate title to display
                 updateSearch={this.updateKeyDropdown}
-                schemaHeader={true} 
+                schemaFieldType={SchemaFieldType.Header} 
                 GetValue={() => {
                     if (SchemaColumnHeader.isDefaultField(this.fieldKey)) return '';
                     else if (this._altTitle) return this._altTitle;
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 107e29754..f6d99b47e 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -121,6 +121,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
     setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false;
     columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
     computeRowIndex = () => this.schemaView?.rowIndex(this.Document);
+    findCellRefs = (text: string) => this.schemaView?.findCellRefs(text);
     render() {
         return (
             <div
@@ -163,6 +164,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                 <div className="row-cells">
                     {this.schemaView?.columnKeys?.map((key, index) => (
                         <SchemaTableCell
+                            getCellRefs={this.findCellRefs}
                             isolatedSelection={this.isolatedSelection}
                             key={key}
                             rowSelected={this._props.isSelected}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index c8bd48019..51555fa61 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -60,6 +60,7 @@ export interface SchemaTableCellProps {
     rootSelected?: () => boolean;
     rowSelected: () => boolean;
     isolatedSelection: [boolean, boolean];
+    getCellRefs: (text: string) => any;
 }
 
 function selectedCell(props: SchemaTableCellProps) {
@@ -72,6 +73,9 @@ function selectedCell(props: SchemaTableCellProps) {
 
 @observer
 export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellProps> {
+
+    @observable _highlighted: boolean = false;
+
     constructor(props: SchemaTableCellProps) {
         super(props);
         makeObservable(this);
@@ -186,6 +190,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                         }
                         const hasNoLayout =  Doc.IsDataProto(fieldProps.Document) ? true : undefined; // the "delegate" is a a data document so never write to it's proto
                         const ret = Doc.SetField(fieldProps.Document, this._props.fieldKey.replace(/^_/, ''), value, hasNoLayout);
+                        this._props.getCellRefs(value);
                         this._props.finishEdit?.();
                         return ret;
                     }, 'edit schema cell')}
-- 
cgit v1.2.3-70-g09d2


From bd3170d3834c6ef9933813afc42f69df044d055b Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Thu, 13 Jun 2024 01:19:46 -0400
Subject: cell highlighting from equations WORKS!

---
 src/client/views/EditableView.tsx                  |  5 +++-
 .../collectionSchema/CollectionSchemaView.tsx      | 30 ++++++++++++++++++++--
 .../collections/collectionSchema/SchemaRowBox.tsx  |  4 +--
 .../collectionSchema/SchemaTableCell.tsx           |  4 +--
 4 files changed, 36 insertions(+), 7 deletions(-)

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

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index f8d6596d8..14af8febb 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -61,6 +61,7 @@ export interface EditableProps {
     onClick?: () => void;
     updateAlt?: (newAlt: string) => void;
     updateSearch?: (value: string) => void;
+    highlightCells?: (text: string) => void;
 }
 
 /**
@@ -74,7 +75,6 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
     private _inputref: HTMLInputElement | HTMLTextAreaElement | null = null;
     private _disposers: { [name: string]: IReactionDisposer } = {};
     _overlayDisposer?: () => void;
-    _highlightsDisposer?: () => void;
     @observable _editing: boolean = false;
 
     constructor(props: EditableProps) {
@@ -91,11 +91,13 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
                         if (this._inputref?.value.startsWith('=') || this._inputref?.value.startsWith(':=')) {
                             this._overlayDisposer?.();
                             this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
+                            this._props.highlightCells?.(this._props.GetValue() ?? '');
                         } 
                     });
                 } else {
                     this._overlayDisposer?.();
                     this._overlayDisposer = undefined;
+                    this._props.highlightCells?.('');
                 }
             },
             { fireImmediately: true }
@@ -127,6 +129,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
             this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
         }
         this._props.updateSearch && this._props.updateSearch(targVal);
+        this._props.highlightCells?.(targVal);
     };
 
     @action
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 4d959e42c..4fc89488d 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -40,6 +40,7 @@ import { GetEffectiveAcl } from '../../../../fields/util';
 import { ContextMenuProps } from '../../ContextMenuItem';
 import { truncate } from 'lodash';
 import { DocumentManager } from '../../../util/DocumentManager';
+import { TbHemispherePlus } from 'react-icons/tb';
 
 const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore
 
@@ -99,6 +100,8 @@ export class CollectionSchemaView extends CollectionSubView() {
     @observable _colBeingDragged: boolean = false;
     @observable _colKeysFiltered: boolean = false;
     @observable _cellTags: ObservableMap = new ObservableMap<Doc, Array<string>>();
+    @observable _highlightedCells: Array<HTMLDivElement> = [];
+    @observable _cellHighlightColors: ObservableMap = new ObservableMap<HTMLDivElement, string>();
     @observable _docs: Doc[] = [];
 
     // target HTMLelement portal for showing a popup menu to edit cell values.
@@ -508,12 +511,35 @@ export class CollectionSchemaView extends CollectionSubView() {
             if (this.columnKeys.includes(field)) {cells.push(this.getCellElement(doc, field))}
         })
 
-        console.log(cells);
-
         return cells;
     }
 
+    removeCellHighlights = () => {
+        this._highlightedCells.forEach(cell => cell.style.border = '');
+        this._highlightedCells = [];
+    }
+
+    highlightCells = (text: string) => {
+        this.removeCellHighlights();
 
+        const randNum = (): number => {return Math.floor(Math.random() * (255 - 1));}
+        const randomRGBColor = (): string => {
+            const r = randNum(); const g = randNum(); const b = randNum(); // prettier-ignore
+            return `rgb(${r}, ${g}, ${b})`;
+        }
+
+        const cellsToHighlight = this.findCellRefs(text);
+        this._highlightedCells = [...cellsToHighlight];
+        this._highlightedCells.forEach(cell => {
+            if (!this._cellHighlightColors.has(cell)) {this._cellHighlightColors.set(cell, `solid 2px ${randomRGBColor()}`)}
+            cell.style.border = this._cellHighlightColors.get(cell);
+        });
+        // const cellsToRemove = [];
+        // this._highlightedCells.forEach(cell => !cellsToHighlight.includes(cell) && cellsToRemove.push(cell));
+        // this._highlightedCells = this._highlightedCells.filter(cell => cellsToHighlight.includes(cell));
+        // const cellsToAdd = cellsToHighlight.filter(cell => !this._highlightedCells.includes(cell));
+        // this._highlightedCells = this._highlightedCells.concat(cellsToAdd);
+    }
 
     @action
     addRowRef = (doc: Doc, ref: HTMLDivElement) => this._rowEles.set(doc, ref);
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index f6d99b47e..4902a49ff 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -121,7 +121,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
     setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false;
     columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
     computeRowIndex = () => this.schemaView?.rowIndex(this.Document);
-    findCellRefs = (text: string) => this.schemaView?.findCellRefs(text);
+    highlightCells = (text: string) => this.schemaView?.highlightCells(text);
     render() {
         return (
             <div
@@ -164,7 +164,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                 <div className="row-cells">
                     {this.schemaView?.columnKeys?.map((key, index) => (
                         <SchemaTableCell
-                            getCellRefs={this.findCellRefs}
+                            highlightCells={this.highlightCells}
                             isolatedSelection={this.isolatedSelection}
                             key={key}
                             rowSelected={this._props.isSelected}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 51555fa61..50ec2f978 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -60,7 +60,7 @@ export interface SchemaTableCellProps {
     rootSelected?: () => boolean;
     rowSelected: () => boolean;
     isolatedSelection: [boolean, boolean];
-    getCellRefs: (text: string) => any;
+    highlightCells: (text: string) => void;
 }
 
 function selectedCell(props: SchemaTableCellProps) {
@@ -175,6 +175,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                     pointerEvents: this.lockedInteraction ? 'none' : pointerEvents,
                 }}>
                 <EditableView
+                    highlightCells={this._props.highlightCells}
                     ref={r => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)}
                     oneLine={this._props.oneLine}
                     allowCRs={this._props.allowCRs}
@@ -190,7 +191,6 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                         }
                         const hasNoLayout =  Doc.IsDataProto(fieldProps.Document) ? true : undefined; // the "delegate" is a a data document so never write to it's proto
                         const ret = Doc.SetField(fieldProps.Document, this._props.fieldKey.replace(/^_/, ''), value, hasNoLayout);
-                        this._props.getCellRefs(value);
                         this._props.finishEdit?.();
                         return ret;
                     }, 'edit schema cell')}
-- 
cgit v1.2.3-70-g09d2


From 20128eb11d5146e9f199d04a94ca9a6b5ac109d7 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Thu, 20 Jun 2024 14:33:28 -0400
Subject: some progress on eq text highlighting

---
 .../collectionSchema/CollectionSchemaView.scss     |  5 +++
 .../collectionSchema/CollectionSchemaView.tsx      |  4 ++-
 .../collectionSchema/SchemaCellField.tsx           | 37 +++++++++++++++++-----
 .../collections/collectionSchema/SchemaRowBox.tsx  |  6 ++++
 .../collectionSchema/SchemaTableCell.tsx           |  6 +++-
 5 files changed, 48 insertions(+), 10 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
index d1f1e3a13..6b53eb1cc 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
@@ -313,3 +313,8 @@
     }
 }
 
+.schemaField-editing {
+    outline: none;
+}
+
+
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index c287b7d44..5c8a84163 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -533,7 +533,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         return cell;
     }
 
-    findCellRefs = (text: string) => {
+    findCellRefs = (text: string, retRawMatches?: boolean) => {
         const pattern = /(this|d(\d+))\.(\w+)/g;
         interface Match { docRef: string; field: string; }
 
@@ -545,6 +545,8 @@ export class CollectionSchemaView extends CollectionSubView() {
             matches.push({ docRef, field: match[3] });
         }
 
+        if (retRawMatches) return matches;
+
         const cells: Array<any> = [];
         matches.forEach((match: Match) => {
             const {docRef, field} = match;
diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index 3af3b1d61..4ba8c8469 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -15,6 +15,7 @@ export interface SchemaCellFieldProps {
     highlightCells?: (text: string) => void;
     GetValue(): string | undefined;
     SetValue(value: string, shiftDown?: boolean, enterKey?: boolean): boolean;
+    func: (text: string, raw: boolean) => HTMLDivElement[] | [];
 }
 
 @observer
@@ -72,10 +73,25 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         this.finalizeEdit(false, true, false);
     }
 
+    chunkContent = (content: string) => {
+        const matches = this._props.func(content, true);
+        const cells = this._props.func(content, false);
+        let chunkedText = content;
+        let matchNum = 0;
+        matches.forEach((docRef, field) => {
+            console.log('cell: ' + cells[matchNum] + ' border: ' + cells[matchNum].style.borderTop)
+            chunkedText = chunkedText.replace(`d5.type`, `<span style="color: ${cells[matchNum].style.borderTop.replace('2px solid', '')}">d5.type</span>`);
+            ++matchNum;
+        })
+        return chunkedText;
+    }
+
     @action 
     setContent = (content: string) => {
-        this._displayedContent = content;
-    };
+        console.log(this.chunkContent(content));
+        this._displayedContent = this.chunkContent(content);
+        console.log('displayed: ' + this._displayedContent);
+    }
 
     @action
     setIsFocused = (value: boolean) => {
@@ -126,10 +142,13 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             }
             return false;
         }
+
+        setRange(this._inputref.childNodes);
     };
 
     onChange = (e: FormEvent<HTMLDivElement>) => {
         const cursorPos = this.cursorPosition;
+        const prevVal = this._content;
         const targVal = e.currentTarget.innerText;
         if (!(targVal.startsWith(':=') || targVal.startsWith('='))) {
             this._overlayDisposer?.();
@@ -138,8 +157,10 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
         }
         this._content = targVal;
-        this.setContent(targVal);
-        setTimeout(() => this.restoreCursorPosition(cursorPos), 0);
+        if (this._props.func(targVal, true).length > this._props.func(prevVal, true).length) {
+            this.setContent(targVal);
+            setTimeout(() => this.restoreCursorPosition(cursorPos), 0);
+        }
         this._props.highlightCells?.(targVal);
     };
 
@@ -208,15 +229,15 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             this._props.fieldContents ? <FieldView {...this._props.fieldContents} /> : this.props.contents ? this._props.contents?.valueOf() : ''
         }
         </span>
-    };
+    }
 
     renderEditor = () => {
         return (
             <div 
             contentEditable
-            className='editableView-static'
+            className='schemaField-editing'
             ref={r => { this._inputref = r; }}
-            style={{ overflow: 'auto', minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20, }}
+            style={{ outline: 'none', overflow: 'auto', minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20, }}
             onBlur={e => this.finalizeEdit(false, true, false)}
             autoFocus
             onInput={this.onChange}
@@ -228,7 +249,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             >
             </div>
         );
-    };
+    }
 
     render() {
         const gval = this._props.GetValue()?.replace(/\n/g, '\\r\\n');
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 4902a49ff..121605a2b 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -122,6 +122,10 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
     columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
     computeRowIndex = () => this.schemaView?.rowIndex(this.Document);
     highlightCells = (text: string) => this.schemaView?.highlightCells(text);
+    equationHighlightRef = (text: string) => {
+    
+    }
+    eqHighlightFunc = (text: string, raw: boolean) => {return this.schemaView.findCellRefs(text, raw)};
     render() {
         return (
             <div
@@ -164,6 +168,8 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                 <div className="row-cells">
                     {this.schemaView?.columnKeys?.map((key, index) => (
                         <SchemaTableCell
+                            func={this.eqHighlightFunc}
+                            equationHighlightRef={this.schemaView._cellHighlightColors}
                             highlightCells={this.highlightCells}
                             isolatedSelection={this.isolatedSelection}
                             key={key}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 74c001397..74ee46065 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -3,7 +3,7 @@
 /* eslint-disable no-use-before-define */
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Popup, Size, Type } from 'browndash-components';
-import { action, computed, makeObservable, observable } from 'mobx';
+import { ObservableMap, action, computed, makeObservable, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import { extname } from 'path';
 import * as React from 'react';
@@ -62,6 +62,9 @@ export interface SchemaTableCellProps {
     rowSelected: () => boolean;
     isolatedSelection: [boolean, boolean];
     highlightCells: (text: string) => void;
+    equationHighlightRef: ObservableMap<HTMLDivElement, string>;
+    func: (text: string, raw: boolean) => HTMLDivElement[] | [];
+
 }
 
 function selectedCell(props: SchemaTableCellProps) {
@@ -179,6 +182,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                 }}>
                 <SchemaCellField
                     highlightCells={this.adjustedHighlight}
+                    func={this._props.func}
                     ref={r => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)}
                     oneLine={this._props.oneLine}
                     contents={undefined}
-- 
cgit v1.2.3-70-g09d2


From 83a2f119bf908d07e08ac89171e73d2211e1eb8f Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Thu, 20 Jun 2024 17:50:00 -0400
Subject: eq highlight working 70%

---
 .../collectionSchema/SchemaCellField.tsx           | 35 +++++++++++++++-------
 .../collections/collectionSchema/SchemaRowBox.tsx  |  2 +-
 .../collectionSchema/SchemaTableCell.tsx           |  1 +
 3 files changed, 27 insertions(+), 11 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index 4ba8c8469..6663fb68f 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -6,12 +6,15 @@ import { DocumentIconContainer } from "../../nodes/DocumentIcon";
 import React, { FormEvent } from "react";
 import { FieldView, FieldViewProps } from "../../nodes/FieldView";
 import { ObjectField } from "../../../../fields/ObjectField";
+import { Doc } from "../../../../fields/Doc";
+import { DocumentView } from "../../nodes/DocumentView";
 
 export interface SchemaCellFieldProps {
     contents: any;
     fieldContents?: FieldViewProps;
     editing?: boolean;
     oneLine?: boolean;
+    Document: Doc;
     highlightCells?: (text: string) => void;
     GetValue(): string | undefined;
     SetValue(value: string, shiftDown?: boolean, enterKey?: boolean): boolean;
@@ -33,7 +36,11 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         makeObservable(this);
     }
 
+    get docIndex(){return DocumentView.getDocViewIndex(this._props.Document);} // prettier-ignore
+
     componentDidMount(): void {
+        this._content = this.props.GetValue() ?? '';
+        this.setContent(this._content);
         this._disposers.editing = reaction(
             () => this._editing,
             editing => {
@@ -43,6 +50,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
                             this._overlayDisposer?.();
                             this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
                             this._props.highlightCells?.(this._props.GetValue() ?? '');
+                            this.setContent(this._content);
                         } 
                     });
                 } else {
@@ -53,8 +61,6 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             },
             { fireImmediately: true }
         );
-        this._content = this.props.GetValue() ?? '';
-        this.setContent(this._content);
     }
 
     componentDidUpdate(prevProps: Readonly<SchemaCellFieldProps>) {
@@ -74,13 +80,24 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
     }
 
     chunkContent = (content: string) => {
-        const matches = this._props.func(content, true);
+        const pattern = /(this|d(\d+))\.(\w+)/g;
+        interface Match { docRef: string; field: string; }
+
+        const matches: Match[] = [];
+        let match: RegExpExecArray | null;
+
+        while ((match = pattern.exec(content)) !== null) {
+            const docRef = match[1] === 'this' ? match[1] : match[2]; 
+            matches.push({ docRef, field: match[3] });
+        }
+
         const cells = this._props.func(content, false);
         let chunkedText = content;
         let matchNum = 0;
-        matches.forEach((docRef, field) => {
-            console.log('cell: ' + cells[matchNum] + ' border: ' + cells[matchNum].style.borderTop)
-            chunkedText = chunkedText.replace(`d5.type`, `<span style="color: ${cells[matchNum].style.borderTop.replace('2px solid', '')}">d5.type</span>`);
+        matches.forEach((match: Match) => {
+            const {docRef, field} = match;
+            // const refToUse = docRef === 'this' ? `${this.docIndex}` : docRef;
+            chunkedText = chunkedText.replace(`d${docRef}.${field}`, `<span style="color: ${cells[matchNum].style.borderTop.replace('2px solid', '')}">d${docRef}.${field}</span>`);
             ++matchNum;
         })
         return chunkedText;
@@ -88,9 +105,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
 
     @action 
     setContent = (content: string) => {
-        console.log(this.chunkContent(content));
         this._displayedContent = this.chunkContent(content);
-        console.log('displayed: ' + this._displayedContent);
     }
 
     @action
@@ -157,11 +172,11 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
         }
         this._content = targVal;
+        this._props.highlightCells?.(targVal);
         if (this._props.func(targVal, true).length > this._props.func(prevVal, true).length) {
             this.setContent(targVal);
             setTimeout(() => this.restoreCursorPosition(cursorPos), 0);
         }
-        this._props.highlightCells?.(targVal);
     };
 
     @action
@@ -245,7 +260,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             onPointerDown={e => e.stopPropagation}
             onClick={e => e.stopPropagation}
             onPointerUp={e => e.stopPropagation}
-            dangerouslySetInnerHTML={{ __html: `<span>${this._displayedContent}</span>` }}
+            dangerouslySetInnerHTML={{ __html: this._displayedContent }}
             >
             </div>
         );
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 121605a2b..c0ad95141 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -131,7 +131,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
             <div
                 className="schema-row"
                 onPointerDown={e => this.setCursorIndex(e.clientY)}
-                style={{ height: this._props.PanelHeight(), backgroundColor: this._props.isSelected() ? Colors.LIGHT_BLUE : undefined }}
+                style={{ height: this._props.PanelHeight()}}
                 ref={(row: HTMLDivElement | null) => {
                     row && this.schemaView?.addRowRef?.(this.Document, row);
                     this._ref = row;
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 74ee46065..3233e363a 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -181,6 +181,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                     pointerEvents: this.lockedInteraction ? 'none' : pointerEvents,
                 }}>
                 <SchemaCellField
+                    Document={this._props.Document}
                     highlightCells={this.adjustedHighlight}
                     func={this._props.func}
                     ref={r => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)}
-- 
cgit v1.2.3-70-g09d2


From 22152c38c3e1485c107b321f1ce3894e87c0226f Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Fri, 21 Jun 2024 01:57:54 -0400
Subject: refactor

---
 .../collectionSchema/CollectionSchemaView.tsx            | 16 ++++++++++------
 .../views/collections/collectionSchema/SchemaRowBox.tsx  |  8 +++++++-
 2 files changed, 17 insertions(+), 7 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 5c8a84163..992ee2ec9 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -101,8 +101,8 @@ export class CollectionSchemaView extends CollectionSubView() {
     @observable _colBeingDragged: boolean = false;
     @observable _colKeysFiltered: boolean = false;
     @observable _cellTags: ObservableMap = new ObservableMap<Doc, Array<string>>();
-    @observable _highlightedCells: Array<HTMLDivElement> = [];
-    @observable _cellHighlightColors: ObservableMap = new ObservableMap<HTMLDivElement, string[]>();
+    @observable _highlightedCells: Array<[doc: Doc, field: string]> = [];
+    @observable _cellHighlightColors: ObservableMap = new ObservableMap<[doc: Doc, field: string], string[]>();
     @observable _docs: Doc[] = [];
     
     // target HTMLelement portal for showing a popup menu to edit cell values.
@@ -290,7 +290,7 @@ export class CollectionSchemaView extends CollectionSubView() {
                     break;
                 }
                 case 'P': {
-                    this.highlightSortedColumn();
+                    console.log(this._cellHighlightColors)
                     break;
                 }
                 default:
@@ -551,14 +551,17 @@ export class CollectionSchemaView extends CollectionSubView() {
         matches.forEach((match: Match) => {
             const {docRef, field} = match;
             const doc = DocumentManager.Instance.DocumentViews[Number(docRef)].Document;
-            if (this.columnKeys.includes(field)) {cells.push(this.getCellElement(doc, field))}
+            if (this.columnKeys.includes(field)) {cells.push([doc, field])}
         })
 
         return cells;
     }
 
     removeCellHighlights = () => {
-        this._highlightedCells.forEach(cell => {cell.style.border = ''; cell.style.backgroundColor = '';});
+        this._highlightedCells.forEach(info => {
+            const cell = this.getCellElement(info[0], info[1]);
+            cell.style.border = ''; cell.style.backgroundColor = '';
+        });
         this._highlightedCells = [];
     }
 
@@ -580,8 +583,9 @@ export class CollectionSchemaView extends CollectionSubView() {
 
         const cellsToHighlight = this.findCellRefs(text);
         this._highlightedCells = [...cellsToHighlight];
-        this._highlightedCells.forEach(cell => {
+        this._highlightedCells.forEach(info => {
             const color = randomRGBColor();
+            const cell = this.getCellElement(info[0], info[1]);
             if (!this._cellHighlightColors.has(cell)) {this._cellHighlightColors.set(cell, new Array<string>(`solid 2px ${color[0]}`, color[1]))}
             cell.style.border = this._cellHighlightColors.get(cell)[0];
             cell.style.backgroundColor = this._cellHighlightColors.get(cell)[1];
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index c0ad95141..6f6b6decf 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -125,7 +125,13 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
     equationHighlightRef = (text: string) => {
     
     }
-    eqHighlightFunc = (text: string, raw: boolean) => {return this.schemaView.findCellRefs(text, raw)};
+    eqHighlightFunc = (text: string, raw: boolean) => {
+        const info = this.schemaView.findCellRefs(text, raw);
+        if (raw) return info;
+        const cells: HTMLDivElement[] = [];
+        info.forEach(info => {cells.push(this.schemaView.getCellElement(info[0], info[1]))})
+        return cells;
+    };
     render() {
         return (
             <div
-- 
cgit v1.2.3-70-g09d2


From 7f9d92b3e1d0ca433c732936eae767095c9a5e7f Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Sat, 22 Jun 2024 15:47:12 -0400
Subject: work on cell field (numerous bugs fixed: spaces now make new divs,
 invalid refs no longer break things, valid->invalid ref causes update
 properly)

---
 .../collectionSchema/CollectionSchemaView.tsx      |  9 ++-
 .../collectionSchema/SchemaCellField.tsx           | 79 ++++++++++++++--------
 .../collections/collectionSchema/SchemaRowBox.tsx  |  5 +-
 .../collectionSchema/SchemaTableCell.tsx           |  4 +-
 4 files changed, 59 insertions(+), 38 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 308520154..9c4eda3b8 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -533,7 +533,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         return cell;
     }
 
-    findCellRefs = (text: string, retRawMatches?: boolean) => {
+    findCellRefs = (text: string) => {
         const pattern = /(this|d(\d+))\.(\w+)/g;
         interface Match { docRef: string; field: string; }
 
@@ -545,13 +545,12 @@ export class CollectionSchemaView extends CollectionSubView() {
             matches.push({ docRef, field: match[3] });
         }
 
-        if (retRawMatches) return matches;
-
         const cells: Array<any> = [];
         matches.forEach((match: Match) => {
             const {docRef, field} = match;
-            const doc = DocumentManager.Instance.DocumentViews[Number(docRef)].Document;
-            if (this.columnKeys.includes(field)) {cells.push([doc, field])}
+            const docView = DocumentManager.Instance.DocumentViews[Number(docRef)];
+            const doc = docView?.Document ?? undefined;
+            if (this.columnKeys.includes(field) && this._docs.includes(doc)) {cells.push([doc, field])}
         })
 
         return cells;
diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index dcfa4f6f2..e2aa27a95 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -18,7 +18,7 @@ export interface SchemaCellFieldProps {
     highlightCells?: (text: string) => void;
     GetValue(): string | undefined;
     SetValue(value: string, shiftDown?: boolean, enterKey?: boolean): boolean;
-    func: (text: string, raw: boolean) => HTMLDivElement[] | [];
+    getCells: (text: string) => HTMLDivElement[] | [];
 }
 
 @observer
@@ -26,7 +26,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
 
     private _disposers: { [name: string]: IReactionDisposer } = {};
     private _inputref: HTMLDivElement | null = null;
-    private _content: string = '';
+    private _unrenderedContent: string = '';
     _overlayDisposer?: () => void;
     @observable _editing: boolean = false;
     @observable _displayedContent = '';
@@ -40,8 +40,8 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
 
     componentDidMount(): void {
         setTimeout(() => { 
-            this._content = this._props.GetValue() ?? '';
-            this.setContent(this._content);
+            this._unrenderedContent = this._props.GetValue() ?? '';
+            this.setContent(this._unrenderedContent, true);
         }, 0); //must be moved to end of batch or else other docs aren't loaded, so render as d-1 in function
         this._disposers.editing = reaction(
             () => this._editing,
@@ -52,8 +52,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
                             this._overlayDisposer?.();
                             this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
                             this._props.highlightCells?.(this._props.GetValue() ?? '');
-                            if (this._props.Document.type === 'collection') console.log('highlight: ' + this._props.GetValue())
-                            this.setContent(this._content);
+                            this.setContent(this._unrenderedContent, true);
                         } 
                     });
                 } else {
@@ -82,33 +81,44 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         this.finalizeEdit(false, true, false);
     }
 
-    chunkContent = (content: string) => {
-        const pattern = /(this|d(\d+))\.(\w+)/g;
-        interface Match { docRef: string; field: string; }
+    makeSpans = (content: string) => {
+        let chunkedText = content;
+        chunkedText = chunkedText.replace(/ +/g, (match) => {
+            const spanSpaces = '&nbsp;'.repeat(match.length);
+            return `<span>${spanSpaces}</span>`;
+        });
 
-        const matches: Match[] = [];
+        const pattern = /(this|d(\d+))\.(\w+)/g;
+        const matches: string[] = [];
         let match: RegExpExecArray | null;
 
+        const cells: Map<string, HTMLDivElement> = new Map();
+
         while ((match = pattern.exec(content)) !== null) {
-            const docRef = match[1] === 'this' ? match[1] : match[2]; 
-            matches.push({ docRef, field: match[3] });
+            const cell = this._props.getCells(match[0]);
+            if (cell.length) {
+                matches.push(match[0]);
+                cells.set(match[0], cell[0])
+            }
         }
 
-        const cells = this._props.func(content, false);
-        let chunkedText = content;
         let matchNum = 0;
-        matches.forEach((match: Match) => {
-            const {docRef, field} = match;
+        matches.forEach((match: string) => {
             // const refToUse = docRef === 'this' ? `${this.docIndex}` : docRef;
-            chunkedText = chunkedText.replace(`d${docRef}.${field}`, `<span style="color: ${cells[matchNum].style.borderTop.replace('2px solid', '')}">d${docRef}.${field}</span>`);
+            chunkedText = chunkedText.replace(match, `<span style="color: ${cells.get(match)?.style.borderTop.replace('2px solid', '')}">${match}</span>`);
             ++matchNum;
         })
+
         return chunkedText;
     }
 
     @action 
-    setContent = (content: string) => {
-        this._displayedContent = this.chunkContent(content);
+    setContent = (content: string, restoreCursorPos?: boolean) => {
+        this._displayedContent = this.makeSpans(content);
+        if (restoreCursorPos) { 
+            const cursorPos = this.cursorPosition;
+            setTimeout(() => this.restoreCursorPosition(cursorPos), 0);
+        }
     }
 
     @action
@@ -164,9 +174,13 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         setRange(this._inputref.childNodes);
     };
 
+    shouldUpdate = (prevVal: string, currVal: string) => {
+        if (this._props.getCells(currVal).length !== this._props.getCells(prevVal).length) return true;
+        //if (contains self-ref pattern)
+    };
+
     onChange = (e: FormEvent<HTMLDivElement>) => {
-        const cursorPos = this.cursorPosition;
-        const prevVal = this._content;
+        const prevVal = this._unrenderedContent;
         const targVal = e.currentTarget.innerText;
         if (!(targVal.startsWith(':=') || targVal.startsWith('='))) {
             this._overlayDisposer?.();
@@ -174,12 +188,9 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         } else if (!this._overlayDisposer) {
             this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
         }
-        this._content = targVal;
+        this._unrenderedContent = targVal;
         this._props.highlightCells?.(targVal);
-        if (this._props.func(targVal, true).length > this._props.func(prevVal, true).length) {
-            this.setContent(targVal);
-            setTimeout(() => this.restoreCursorPosition(cursorPos), 0);
-        }
+        if (this.shouldUpdate(prevVal, targVal)) {this.setContent(targVal, true)};
     };
 
     @action
@@ -206,6 +217,18 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             case 'ArrowUp': case 'ArrowDown': case 'ArrowLeft': case 'ArrowRight': //prettier-ignore
                 e.stopPropagation();
                 break;
+            case ' ':
+                e.stopPropagation();
+                setTimeout(() => {
+                    this.setContent(this._unrenderedContent);
+                    const cursorPos = this.cursorPosition;
+                    setTimeout(() => this.restoreCursorPosition(cursorPos), 0);
+                }
+                , 0);
+                break;
+            case 'u': // for some reason 'u' otherwise exits the editor
+                e.stopPropagation();
+                break;
             case 'Shift': case 'Alt': case 'Meta': case 'Control': case ':': //prettier-ignore
                 break;
             // eslint-disable-next-line no-fallthrough
@@ -225,8 +248,8 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
 
     @action
     finalizeEdit(shiftDown: boolean, lostFocus: boolean, enterKey: boolean) {
-        this.setContent(this._content);
-        if (this._props.SetValue(this._content, shiftDown, enterKey)) {
+        this.setContent(this._unrenderedContent);
+        if (this._props.SetValue(this._unrenderedContent, shiftDown, enterKey)) {
             this._editing = false;
         } else {
             this._editing = false;
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 6f6b6decf..f4320dc09 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -125,9 +125,8 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
     equationHighlightRef = (text: string) => {
     
     }
-    eqHighlightFunc = (text: string, raw: boolean) => {
-        const info = this.schemaView.findCellRefs(text, raw);
-        if (raw) return info;
+    eqHighlightFunc = (text: string) => {
+        const info = this.schemaView.findCellRefs(text);
         const cells: HTMLDivElement[] = [];
         info.forEach(info => {cells.push(this.schemaView.getCellElement(info[0], info[1]))})
         return cells;
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 94fd9ec7d..ab384a487 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -63,7 +63,7 @@ export interface SchemaTableCellProps {
     isolatedSelection: [boolean, boolean];
     highlightCells: (text: string) => void;
     equationHighlightRef: ObservableMap<HTMLDivElement, string>;
-    func: (text: string, raw: boolean) => HTMLDivElement[] | [];
+    func: (text: string) => HTMLDivElement[] | [];
 
 }
 
@@ -184,7 +184,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                 <SchemaCellField
                     Document={this._props.Document}
                     highlightCells={this.adjustedHighlight}
-                    func={this._props.func}
+                    getCells={this._props.func}
                     ref={r => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)}
                     oneLine={this._props.oneLine}
                     contents={undefined}
-- 
cgit v1.2.3-70-g09d2


From 9fab1b3ac096138fba3a99a2515ec44b526a3956 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Sun, 23 Jun 2024 02:54:24 -0400
Subject: text highlight works with 'this.' format

---
 src/client/views/collections/collectionSchema/SchemaCellField.tsx | 7 +++++--
 src/client/views/collections/collectionSchema/SchemaRowBox.tsx    | 2 ++
 src/client/views/collections/collectionSchema/SchemaTableCell.tsx | 8 ++++----
 3 files changed, 11 insertions(+), 6 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index fc191014c..aa6c382ef 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -53,7 +53,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
                         if (this._inputref?.innerText.startsWith('=') || this._inputref?.innerText.startsWith(':=')) {
                             this._overlayDisposer?.();
                             this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
-                            this._props.highlightCells?.(this._props.GetValue() ?? '');
+                            this._props.highlightCells?.(this._unrenderedContent);
                             this.setContent(this._unrenderedContent, true);
                         } 
                     });
@@ -98,15 +98,18 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
 
         while ((match = pattern.exec(content)) !== null) {
             const cell = this._props.getCells(match[0]);
+            //console.log(cell)
             if (cell.length) {
                 matches.push(match[0]);
                 cells.set(match[0], cell[0])
             }
         }
 
+        //console.log(cells)
+
         let matchNum = 0;
         matches.forEach((match: string) => {
-            // const refToUse = docRef === 'this' ? `${this.docIndex}` : docRef;
+            const adjMatch = match.replace('this.', `d${this.docIndex}`)
             chunkedText = chunkedText.replace(match, `<span style="color: ${cells.get(match)?.style.borderTop.replace('2px solid', '')}">${match}</span>`);
             ++matchNum;
         })
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index f4320dc09..45f178815 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -22,6 +22,7 @@ import { ContextMenu } from '../../ContextMenu';
 import { CollectionFreeFormView } from '../collectionFreeForm';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
+import { infoState } from '../collectionFreeForm/CollectionFreeFormInfoState';
 
 interface SchemaRowBoxProps extends FieldViewProps {
     rowIndex: number;
@@ -129,6 +130,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         const info = this.schemaView.findCellRefs(text);
         const cells: HTMLDivElement[] = [];
         info.forEach(info => {cells.push(this.schemaView.getCellElement(info[0], info[1]))})
+        console.log('info: ' + info + ' cells: ' + cells);
         return cells;
     };
     render() {
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index ab384a487..6ccada48c 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -144,10 +144,10 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         return { color, textDecoration, fieldProps, cursor, pointerEvents };
     }
         
-    adjustedHighlight = (field: string) => {
+    adjustSelfReference = (field: string) => {
         const pattern = /\bthis.\b/g;  
         const modField = field.replace(pattern, `d${this.docIndex}.`);
-        this._props.highlightCells(modField);
+        return modField;
     }
 
     // parses a field from the "idToDoc(####)" format to DocumentId (d#) format for readability
@@ -183,8 +183,8 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                 }}>
                 <SchemaCellField
                     Document={this._props.Document}
-                    highlightCells={this.adjustedHighlight}
-                    getCells={this._props.func}
+                    highlightCells={(text: string) => this._props.highlightCells(this.adjustSelfReference(text))}
+                    getCells={(text: string) => this._props.func(this.adjustSelfReference(text))}
                     ref={r => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)}
                     oneLine={this._props.oneLine}
                     contents={undefined}
-- 
cgit v1.2.3-70-g09d2


From b2691d6119dfa1f192ac6eb19650f44742b253f5 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Sun, 23 Jun 2024 03:36:21 -0400
Subject: col filling (really external setting of cell fieldval) works properly
 (reaction); moved 'remove doc' option to bottom of row menu

---
 .../collectionSchema/CollectionSchemaView.tsx           |  6 +++---
 .../collections/collectionSchema/SchemaCellField.tsx    | 17 +++++++++++------
 .../views/collections/collectionSchema/SchemaRowBox.tsx | 13 ++++++-------
 .../collections/collectionSchema/SchemaTableCell.tsx    |  4 +---
 4 files changed, 21 insertions(+), 19 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 9c4eda3b8..2a84efa7c 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -829,9 +829,9 @@ export class CollectionSchemaView extends CollectionSubView() {
         this.closeColumnMenu();
     };
 
-    setCellValues = (key: string, value: string) => {
-        if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing &&Doc.SetField(doc, key, value)); // if only one cell selected, fill all
-        else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); // else only fill selected cells
+    setColumnValues = (key: string, value: string) => {
+        if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing &&Doc.SetField(doc, key, value)); 
+        else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); 
         return true;
     };
 
diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index aa6c382ef..e85bf75e6 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -36,7 +36,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         makeObservable(this);
         setTimeout(() => { 
             this._unrenderedContent = this._props.GetValue() ?? '';
-            this.setContent(this._unrenderedContent, true);
+            this.setContent(this._unrenderedContent);
         }, 0); //must be moved to end of batch or else other docs aren't loaded, so render as d-1 in function
     }
 
@@ -65,6 +65,13 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             },
             { fireImmediately: true }
         );
+        this._disposers.fieldUpdate = reaction(
+            () => this._props.GetValue(),
+            fieldVal => {
+                this._unrenderedContent = fieldVal ?? '';
+                this.setContent(this._unrenderedContent);
+            }
+        )
     }
 
     componentDidUpdate(prevProps: Readonly<SchemaCellFieldProps>) {
@@ -79,7 +86,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
 
     componentWillUnmount(): void {
         this._overlayDisposer?.();
-        this._disposers.editing?.();
+        Object.values(this._disposers).forEach(disposer => disposer?.());
         this.finalizeEdit(false, true, false);
     }
 
@@ -98,15 +105,12 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
 
         while ((match = pattern.exec(content)) !== null) {
             const cell = this._props.getCells(match[0]);
-            //console.log(cell)
             if (cell.length) {
                 matches.push(match[0]);
                 cells.set(match[0], cell[0])
             }
         }
 
-        //console.log(cells)
-
         let matchNum = 0;
         matches.forEach((match: string) => {
             const adjMatch = match.replace('this.', `d${this.docIndex}`)
@@ -237,6 +241,8 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             case 'Shift': case 'Alt': case 'Meta': case 'Control': case ':': //prettier-ignore
                 break;
             // eslint-disable-next-line no-fallthrough
+            case 'P':
+                break;
             default:
                 break;
         }
@@ -253,7 +259,6 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
 
     @action
     finalizeEdit(shiftDown: boolean, lostFocus: boolean, enterKey: boolean) {
-        this.setContent(this._unrenderedContent);
         if (this._props.SetValue(this._unrenderedContent, shiftDown, enterKey)) {
             this._editing = false;
         } else {
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 45f178815..d2c0d891f 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -60,11 +60,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
 
     openContextMenu = (x: number, y: number) => {
         ContextMenu.Instance.clearItems();
-        ContextMenu.Instance.addItem({
-            description: `Close doc`,
-            event: () => this.schemaView.removeDoc(this.Document),
-            icon: 'minus',
-        });
         ContextMenu.Instance.addItem({
             description: this.Document._lockedSchemaEditing ? 'Unlock field editing' : 'Lock field editing',
             event: () => this.Document._lockedSchemaEditing = !this.Document._lockedSchemaEditing,
@@ -75,6 +70,11 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
             event: () => this._props.addDocTab(this.Document, OpenWhere.addRight),
             icon: 'magnifying-glass',
         });
+        ContextMenu.Instance.addItem({
+            description: `Close doc`,
+            event: () => this.schemaView.removeDoc(this.Document),
+            icon: 'minus',
+        });
         const childDocs = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)])
         if (this.Document.type === 'collection' && childDocs.length) {
                 ContextMenu.Instance.addItem({
@@ -119,7 +119,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
     selectCell = (doc: Doc, col: number, shift: boolean, ctrl: boolean) => this.schemaView?.selectCell(doc, col, shift, ctrl);
     deselectCell = () => this.schemaView?.deselectAllCells();
     selectedCells = () => this.schemaView?._selectedDocs;
-    setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false;
+    setColumnValues = (field: any, value: any) => this.schemaView?.setColumnValues(field, value) ?? false;
     columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
     computeRowIndex = () => this.schemaView?.rowIndex(this.Document);
     highlightCells = (text: string) => this.schemaView?.highlightCells(text);
@@ -130,7 +130,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         const info = this.schemaView.findCellRefs(text);
         const cells: HTMLDivElement[] = [];
         info.forEach(info => {cells.push(this.schemaView.getCellElement(info[0], info[1]))})
-        console.log('info: ' + info + ' cells: ' + cells);
         return cells;
     };
     render() {
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 6ccada48c..aa8401502 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -145,14 +145,12 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
     }
         
     adjustSelfReference = (field: string) => {
-        const pattern = /\bthis.\b/g;  
-        const modField = field.replace(pattern, `d${this.docIndex}.`);
+        const modField = field.replace(/\bthis.\b/g, `d${this.docIndex}.`);
         return modField;
     }
 
     // parses a field from the "idToDoc(####)" format to DocumentId (d#) format for readability
     cleanupField = (field: string) => {
-        if (field === ':=d6.type + d4.type + d3.type') console.log(true)
         const idPattern = /idToDoc\((.*?)\)/g;
         let modField = field.slice();
         let matches;
-- 
cgit v1.2.3-70-g09d2


From 6a3d0cc899020710d5b9aabe164649c686467024 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Tue, 25 Jun 2024 01:14:06 -0400
Subject: progress on refSelect (single click to add cell to equation)

---
 .../collectionSchema/CollectionSchemaView.tsx      | 135 +++++++++++----------
 .../collectionSchema/SchemaCellField.tsx           |  25 ++--
 .../collections/collectionSchema/SchemaRowBox.tsx  |   8 +-
 .../collectionSchema/SchemaTableCell.tsx           |  11 +-
 4 files changed, 106 insertions(+), 73 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 48c34c647..c3dc4bad6 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -42,6 +42,7 @@ import { truncate } from 'lodash';
 import { DocumentManager } from '../../../util/DocumentManager';
 import { TbHemispherePlus } from 'react-icons/tb';
 import { docs_v1 } from 'googleapis';
+import { SchemaCellField } from './SchemaCellField';
 
 const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore
 
@@ -104,7 +105,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     @observable _highlightedCellsInfo: Array<[doc: Doc, field: string]> = [];
     @observable _cellHighlightColors: ObservableMap = new ObservableMap<string, string[]>();
     @observable _docs: Doc[] = [];
-    @observable _inCellSelectMode: boolean = false;
+    @observable _referenceSelectMode = {enabled: false, currEditing: undefined}
     
     // target HTMLelement portal for showing a popup menu to edit cell values.
     public get MenuTarget() {
@@ -113,7 +114,7 @@ export class CollectionSchemaView extends CollectionSubView() {
 
     @computed get _selectedDocs() {
         // get all selected documents then filter out any whose parent is not this schema document
-        const selected = DocumentView.SelectedDocs().filter(doc => this.docs.includes(doc));
+        const selected = DocumentView.SelectedDocs().filter(doc => this.docs.includes(doc) && this._selectedCells.includes(doc));
         if (!selected.length) {
             // if no schema doc is directly selected, test if a child of a schema doc is selected (such as in the preview window)
             const childOfSchemaDoc = DocumentView.SelectedDocs().find(sel => DocumentView.getContextPath(sel, true).includes(this.Document));
@@ -651,7 +652,19 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     @action
-    selectCell = (doc: Doc, col: number, shiftKey: boolean, ctrlKey: boolean) => {
+    selectCell = (doc: Doc | undefined, col: number, shiftKey: boolean, ctrlKey: boolean) => {
+        if (!doc) return;
+
+        if (this._referenceSelectMode.enabled) {
+            const docIndex = DocumentView.getDocViewIndex(doc);
+            const field = this.columnKeys[col];
+            const refToAdd = `d${docIndex}.${field}`
+            const editedField = this._referenceSelectMode.currEditing ? this._referenceSelectMode.currEditing as SchemaCellField : null;
+            editedField?.appendText(refToAdd);
+            editedField?.setupRefSelect(false);
+            return;
+        }
+
         this.closeColumnMenu();
         if (!shiftKey && !ctrlKey) this.clearSelection();
         !this._selectedCells && (this._selectedCells = []);
@@ -1015,64 +1028,64 @@ export class CollectionSchemaView extends CollectionSubView() {
         this._filterSearchValue = e.target.value;
     };
 
-    @computed get newFieldMenu() {
-        return (
-            <div className="schema-new-key-options">
-                <div className="schema-key-type-option">
-                    <input
-                        type="radio"
-                        name="newFieldType"
-                        checked={this._newFieldType === ColumnType.Number}
-                        onChange={action(() => {
-                            this._newFieldType = ColumnType.Number;
-                            this._newFieldDefault = 0;
-                        })}
-                    />
-                    number
-                </div>
-                <div className="schema-key-type-option">
-                    <input
-                        type="radio"
-                        name="newFieldType"
-                        checked={this._newFieldType === ColumnType.Boolean}
-                        onChange={action(() => {
-                            this._newFieldType = ColumnType.Boolean;
-                            this._newFieldDefault = false;
-                        })}
-                    />
-                    boolean
-                </div>
-                <div className="schema-key-type-option">
-                    <input
-                        type="radio"
-                        name="newFieldType"
-                        checked={this._newFieldType === ColumnType.String}
-                        onChange={action(() => {
-                            this._newFieldType = ColumnType.String;
-                            this._newFieldDefault = '';
-                        })}
-                    />
-                    string
-                </div>
-                <div className="schema-key-default-val">value: {this.fieldDefaultInput}</div>
-                <div className="schema-key-warning">{this._newFieldWarning}</div>
-                <div
-                    className="schema-column-menu-button"
-                    onPointerDown={action(() => {
-                        if (this.documentKeys.includes(this._menuValue)) {
-                            this._newFieldWarning = 'Field already exists';
-                        } else if (this._menuValue.length === 0) {
-                            this._newFieldWarning = 'Field cannot be an empty string';
-                        } else {
-                            this.setKey(this._menuValue, this._newFieldDefault);
-                        }
-                        this._columnMenuIndex = undefined;
-                    })}>
-                    done
-                </div>
-            </div>
-        );
-    }
+    // @computed get newFieldMenu() {
+    //     return (
+    //         <div className="schema-new-key-options">
+    //             <div className="schema-key-type-option">
+    //                 <input
+    //                     type="radio"
+    //                     name="newFieldType"
+    //                     checked={this._newFieldType === ColumnType.Number}
+    //                     onChange={action(() => {
+    //                         this._newFieldType = ColumnType.Number;
+    //                         this._newFieldDefault = 0;
+    //                     })}
+    //                 />
+    //                 number
+    //             </div>
+    //             <div className="schema-key-type-option">
+    //                 <input
+    //                     type="radio"
+    //                     name="newFieldType"
+    //                     checked={this._newFieldType === ColumnType.Boolean}
+    //                     onChange={action(() => {
+    //                         this._newFieldType = ColumnType.Boolean;
+    //                         this._newFieldDefault = false;
+    //                     })}
+    //                 />
+    //                 boolean
+    //             </div>
+    //             <div className="schema-key-type-option">
+    //                 <input
+    //                     type="radio"
+    //                     name="newFieldType"
+    //                     checked={this._newFieldType === ColumnType.String}
+    //                     onChange={action(() => {
+    //                         this._newFieldType = ColumnType.String;
+    //                         this._newFieldDefault = '';
+    //                     })}
+    //                 />
+    //                 string
+    //             </div>
+    //             <div className="schema-key-default-val">value: {this.fieldDefaultInput}</div>
+    //             <div className="schema-key-warning">{this._newFieldWarning}</div>
+    //             <div
+    //                 className="schema-column-menu-button"
+    //                 onPointerDown={action(() => {
+    //                     if (this.documentKeys.includes(this._menuValue)) {
+    //                         this._newFieldWarning = 'Field already exists';
+    //                     } else if (this._menuValue.length === 0) {
+    //                         this._newFieldWarning = 'Field cannot be an empty string';
+    //                     } else {
+    //                         this.setKey(this._menuValue, this._newFieldDefault);
+    //                     }
+    //                     this._columnMenuIndex = undefined;
+    //                 })}>
+    //                 done
+    //             </div>
+    //         </div>
+    //     );
+    // }
 
     onKeysPassiveWheel = (e: WheelEvent) => {
         // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this)
diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index e13763b45..ea46fb432 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -15,6 +15,8 @@ export interface SchemaCellFieldProps {
     editing?: boolean;
     oneLine?: boolean;
     Document: Doc;
+    fieldKey: string;
+    refSelectModeInfo: {enabled: boolean, currEditing: SchemaCellField | undefined};
     highlightCells?: (text: string) => void;
     GetValue(): string | undefined;
     SetValue(value: string, shiftDown?: boolean, enterKey?: boolean): boolean;
@@ -41,10 +43,6 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         }, 0); //must be moved to end of batch or else other docs aren't loaded, so render as d-1 in function
     }
 
-    @computed get inCellSelectMode() {
-        return 
-    }
-
     get docIndex(){return DocumentView.getDocViewIndex(this._props.Document);} // prettier-ignore
 
     componentDidMount(): void {
@@ -66,6 +64,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
                     this._overlayDisposer?.();
                     this._overlayDisposer = undefined;
                     this._props.highlightCells?.('');
+                    this.setupRefSelect(false);
                 }
             },
             { fireImmediately: true }
@@ -127,7 +126,6 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
 
     @action 
     setContent = (content: string, restoreCursorPos?: boolean) => {
-        console.log('content: ' + content)
         this._displayedContent = this.makeSpans(content);
         if (restoreCursorPos) { 
             const cursorPos = this.cursorPosition;
@@ -135,6 +133,12 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         }
     }
 
+    @action
+    appendText = (text: string) => {
+        this._unrenderedContent += text;
+        this.setContent(this._unrenderedContent);
+    }
+
     @action
     setIsFocused = (value: boolean) => {
         const wasFocused = this._editing;
@@ -209,6 +213,12 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         if (this.shouldUpdate(prevVal, targVal)) {this.setContent(targVal, true)};
     };
 
+    setupRefSelect = (enabled: boolean) => {
+        const properties = this._props.refSelectModeInfo;
+        properties.enabled = enabled;
+        properties.currEditing = enabled ? this : undefined;
+    }
+
     @action
     onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
         if (e.nativeEvent.defaultPrevented) return; // hack .. DashFieldView grabs native events, but react ignores stoppedPropagation and preventDefault, so we need to check it here
@@ -234,7 +244,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
                 e.stopPropagation();
                 break;
             case '+': case '*': case '/': case '%': // prettier-ignore
-
+                this.setupRefSelect(true);
                 break;
             case ' ':
                 e.stopPropagation();
@@ -249,12 +259,13 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
                 break;
             case 'u': // for some reason 'u' otherwise exits the editor
                 e.stopPropagation();
+                this.setupRefSelect(false);
                 break;
             case 'Shift': case 'Alt': case 'Meta': case 'Control': case ':': // prettier-ignore
                 break;
             // eslint-disable-next-line no-fallthrough
             default:
-                console.log('default called')
+                this.setupRefSelect(false);
                 break;
         }
     };
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index d2c0d891f..b15804d41 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -96,6 +96,10 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         return ''
     }
 
+    @computed get refSelectModeInfo() {
+        return this.schemaView._referenceSelectMode;
+    }
+
     @computed get menuInfos() {
         const infos: Array<IconProp> = [];
         if (this.Document._lockedSchemaEditing) infos.push('lock');
@@ -123,9 +127,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
     columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
     computeRowIndex = () => this.schemaView?.rowIndex(this.Document);
     highlightCells = (text: string) => this.schemaView?.highlightCells(text);
-    equationHighlightRef = (text: string) => {
-    
-    }
     eqHighlightFunc = (text: string) => {
         const info = this.schemaView.findCellRefs(text);
         const cells: HTMLDivElement[] = [];
@@ -174,6 +175,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                 <div className="row-cells">
                     {this.schemaView?.columnKeys?.map((key, index) => (
                         <SchemaTableCell
+                            refSelectModeInfo={this.refSelectModeInfo}
                             func={this.eqHighlightFunc}
                             equationHighlightRef={this.schemaView._cellHighlightColors}
                             highlightCells={this.highlightCells}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index aa8401502..75b31315e 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -64,7 +64,7 @@ export interface SchemaTableCellProps {
     highlightCells: (text: string) => void;
     equationHighlightRef: ObservableMap<HTMLDivElement, string>;
     func: (text: string) => HTMLDivElement[] | [];
-
+    refSelectModeInfo: {enabled: boolean, currEditing: SchemaCellField | undefined};
 }
 
 function selectedCell(props: SchemaTableCellProps) {
@@ -78,7 +78,7 @@ function selectedCell(props: SchemaTableCellProps) {
 @observer
 export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellProps> {
 
-    @observable _highlighted: boolean = false;
+    // private _fieldRef: SchemaCellField | null = null;
 
     constructor(props: SchemaTableCellProps) {
         super(props);
@@ -143,6 +143,11 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         const pointerEvents: 'all' | 'none' = !readOnly && isRowActive() ? 'all' : 'none';
         return { color, textDecoration, fieldProps, cursor, pointerEvents };
     }
+
+    // @action
+    // appendTextToField = (text: string) => {
+    //     this._fieldRef?.appendText(text);
+    // }
         
     adjustSelfReference = (field: string) => {
         const modField = field.replace(/\bthis.\b/g, `d${this.docIndex}.`);
@@ -180,6 +185,8 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                     pointerEvents: this.lockedInteraction ? 'none' : pointerEvents,
                 }}>
                 <SchemaCellField
+                    fieldKey={this._props.fieldKey}
+                    refSelectModeInfo={this._props.refSelectModeInfo}
                     Document={this._props.Document}
                     highlightCells={(text: string) => this._props.highlightCells(this.adjustSelfReference(text))}
                     getCells={(text: string) => this._props.func(this.adjustSelfReference(text))}
-- 
cgit v1.2.3-70-g09d2


From 54559c677ac3a91e72680b5b7c889d63439edf58 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Tue, 25 Jun 2024 12:10:05 -0400
Subject: focus is no longer lost

---
 src/client/util/SelectionManager.ts                |  1 +
 .../collectionSchema/CollectionSchemaView.tsx      | 26 ++++++++++++----------
 .../collectionSchema/SchemaCellField.tsx           | 11 ++++-----
 .../collections/collectionSchema/SchemaRowBox.tsx  |  3 +++
 .../collectionSchema/SchemaTableCell.tsx           |  8 +++++++
 5 files changed, 32 insertions(+), 17 deletions(-)

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

diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 0b942116c..fc494583f 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -58,6 +58,7 @@ export class SelectionManager {
     });
 
     public static DeselectAll = (except?: Doc): void => {
+        
         const found = this.Instance.SelectedViews.find(dv => dv.Document === except);
         runInAction(() => {
             if (LinkManager.Instance) {
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index c3dc4bad6..3b5a32ca7 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -634,6 +634,7 @@ export class CollectionSchemaView extends CollectionSubView() {
 
     @action
     clearSelection = () => {
+        if (this._referenceSelectMode.enabled) return;
         DocumentView.DeselectAll();
         this.deselectAllCells();
     };
@@ -651,20 +652,19 @@ export class CollectionSchemaView extends CollectionSubView() {
         }
     };
 
-    @action
-    selectCell = (doc: Doc | undefined, col: number, shiftKey: boolean, ctrlKey: boolean) => {
+    selectReference = (doc: Doc | undefined, col: number) => {
         if (!doc) return;
+        const docIndex = DocumentView.getDocViewIndex(doc);
+        const field = this.columnKeys[col];
+        const refToAdd = `d${docIndex}.${field}`
+        const editedField = this._referenceSelectMode.currEditing ? this._referenceSelectMode.currEditing as SchemaCellField : null;
+        editedField?.appendText(refToAdd);
+        editedField?.setupRefSelect(false);
+        return;
+    }
 
-        if (this._referenceSelectMode.enabled) {
-            const docIndex = DocumentView.getDocViewIndex(doc);
-            const field = this.columnKeys[col];
-            const refToAdd = `d${docIndex}.${field}`
-            const editedField = this._referenceSelectMode.currEditing ? this._referenceSelectMode.currEditing as SchemaCellField : null;
-            editedField?.appendText(refToAdd);
-            editedField?.setupRefSelect(false);
-            return;
-        }
-
+    @action
+    selectCell = (doc: Doc, col: number, shiftKey: boolean, ctrlKey: boolean) => {
         this.closeColumnMenu();
         if (!shiftKey && !ctrlKey) this.clearSelection();
         !this._selectedCells && (this._selectedCells = []);
@@ -687,12 +687,14 @@ export class CollectionSchemaView extends CollectionSubView() {
 
     @action
     deselectCell = (doc: Doc) => {
+        console.log('single deselect called')
         this._selectedCells && (this._selectedCells = this._selectedCells.filter(d => d !== doc));
         if (this.rowIndex(doc) === this._lowestSelectedIndex) this._lowestSelectedIndex = Math.min(...this._selectedDocs.map(d => this.rowIndex(d)));
     };
 
     @action
     deselectAllCells = () => {
+        console.log('deselectall called')
         this._selectedCells = [];
         this._lowestSelectedIndex = -1;
     };
diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index 84b4d3462..06d3926a8 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -62,6 +62,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             () => this._editing,
             editing => {
                 if (editing) {
+                    if (this.lastChar !== '+') this.setupRefSelect(false);
                     setTimeout(() => {
                         if (this._inputref?.innerText.startsWith('=') || this._inputref?.innerText.startsWith(':=')) {
                             this._overlayDisposer?.();
@@ -145,8 +146,8 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
 
     @action
     appendText = (text: string) => {
-        this._unrenderedContent += text;
-        this.setContent(this._unrenderedContent);
+        const newText = this._unrenderedContent.concat(text);
+        this.onChange(undefined, newText);
     }
 
     @action
@@ -209,9 +210,9 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         //if (contains self-ref pattern)
     };
 
-    onChange = (e: FormEvent<HTMLDivElement>) => {
+    onChange = (e: FormEvent<HTMLDivElement> | undefined, newText?: string) => {
         const prevVal = this._unrenderedContent;
-        const targVal = e.currentTarget.innerText;
+        const targVal = newText ?? e!.currentTarget.innerText; // TODO: bang
         if (!(targVal.startsWith(':=') || targVal.startsWith('='))) {
             this._overlayDisposer?.();
             this._overlayDisposer = undefined;
@@ -319,7 +320,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             className='schemaField-editing'
             ref={r => { this._inputref = r; }}
             style={{ cursor: 'text', outline: 'none', overflow: 'auto', minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20, }}
-            onBlur={e => this.finalizeEdit(false, true, false)}
+            onBlur={e => {this._props.refSelectModeInfo.enabled ? setTimeout(() => {this.setIsFocused(true)}, 1000) : this.finalizeEdit(false, true, false)}}
             autoFocus
             onInput={this.onChange}
             onKeyDown={this.onKeyDown}
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index b15804d41..3f5c2a90e 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -23,6 +23,7 @@ import { CollectionFreeFormView } from '../collectionFreeForm';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { infoState } from '../collectionFreeForm/CollectionFreeFormInfoState';
+import { TbShieldX } from 'react-icons/tb';
 
 interface SchemaRowBoxProps extends FieldViewProps {
     rowIndex: number;
@@ -127,6 +128,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
     columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
     computeRowIndex = () => this.schemaView?.rowIndex(this.Document);
     highlightCells = (text: string) => this.schemaView?.highlightCells(text);
+    selectReference = (doc: Doc, col: number) => {this.schemaView.selectReference(doc, col)}
     eqHighlightFunc = (text: string) => {
         const info = this.schemaView.findCellRefs(text);
         const cells: HTMLDivElement[] = [];
@@ -175,6 +177,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                 <div className="row-cells">
                     {this.schemaView?.columnKeys?.map((key, index) => (
                         <SchemaTableCell
+                            selectReference={this.selectReference}
                             refSelectModeInfo={this.refSelectModeInfo}
                             func={this.eqHighlightFunc}
                             equationHighlightRef={this.schemaView._cellHighlightColors}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 75b31315e..ef46c44da 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -65,6 +65,7 @@ export interface SchemaTableCellProps {
     equationHighlightRef: ObservableMap<HTMLDivElement, string>;
     func: (text: string) => HTMLDivElement[] | [];
     refSelectModeInfo: {enabled: boolean, currEditing: SchemaCellField | undefined};
+    selectReference: (doc: Doc, col: number) => void;
 }
 
 function selectedCell(props: SchemaTableCellProps) {
@@ -254,6 +255,13 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                 className="schema-table-cell"
                 onContextMenu={e => StopEvent(e)}
                 onPointerDown={action(e => {
+                    if (this._props.refSelectModeInfo.enabled && !selectedCell(this._props)){
+                        e.stopPropagation();
+                        e.preventDefault();
+                        this._props.selectReference(this._props.Document, this._props.col);
+                        return;
+                    }
+
                     const shift: boolean = e.shiftKey;
                     const ctrl: boolean = e.ctrlKey;
                     if (this._props.isRowActive?.()) {
-- 
cgit v1.2.3-70-g09d2


From 2437028db1f273350b0422da0ef3a5f520ffce59 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Wed, 26 Jun 2024 13:48:25 -0400
Subject: self-reference warning added

---
 src/client/views/collections/collectionSchema/SchemaCellField.tsx | 6 +++++-
 src/client/views/collections/collectionSchema/SchemaRowBox.tsx    | 2 +-
 src/client/views/collections/collectionSchema/SchemaTableCell.tsx | 4 ++--
 3 files changed, 8 insertions(+), 4 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index 8e751f4ba..27ca37c2b 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -33,6 +33,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
     @observable _editing: boolean = false;
     @observable _displayedContent = '';
     @observable _inCellSelectMode: boolean = false;
+    @observable _dependencyMessageShown: boolean = false;
 
     constructor(props: SchemaCellFieldProps) {
         super(props);
@@ -300,7 +301,10 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
     @action
     finalizeEdit(shiftDown: boolean, lostFocus: boolean, enterKey: boolean) {
         if (this._unrenderedContent.replace(this.selfRefPattern, '') !== this._unrenderedContent) {
-            console.log('error'); this._editing = false; return;
+            this._dependencyMessageShown ? this._dependencyMessageShown = false :
+            alert("Circular dependency detected. Please update the field.")
+            this._dependencyMessageShown = true;
+            return;
         }
         
         if (this._props.SetValue(this._unrenderedContent, shiftDown, enterKey)) {
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 3f5c2a90e..c9feeac6b 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -179,7 +179,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                         <SchemaTableCell
                             selectReference={this.selectReference}
                             refSelectModeInfo={this.refSelectModeInfo}
-                            func={this.eqHighlightFunc}
+                            eqHighlightFunc={this.eqHighlightFunc}
                             equationHighlightRef={this.schemaView._cellHighlightColors}
                             highlightCells={this.highlightCells}
                             isolatedSelection={this.isolatedSelection}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index ef46c44da..016ab5e69 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -63,7 +63,7 @@ export interface SchemaTableCellProps {
     isolatedSelection: [boolean, boolean];
     highlightCells: (text: string) => void;
     equationHighlightRef: ObservableMap<HTMLDivElement, string>;
-    func: (text: string) => HTMLDivElement[] | [];
+    eqHighlightFunc: (text: string) => HTMLDivElement[] | [];
     refSelectModeInfo: {enabled: boolean, currEditing: SchemaCellField | undefined};
     selectReference: (doc: Doc, col: number) => void;
 }
@@ -190,7 +190,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                     refSelectModeInfo={this._props.refSelectModeInfo}
                     Document={this._props.Document}
                     highlightCells={(text: string) => this._props.highlightCells(this.adjustSelfReference(text))}
-                    getCells={(text: string) => this._props.func(this.adjustSelfReference(text))}
+                    getCells={(text: string) => this._props.eqHighlightFunc(this.adjustSelfReference(text))}
                     ref={r => selectedCell(this._props) && this._props.autoFocus && r?.setIsFocused(true)}
                     oneLine={this._props.oneLine}
                     contents={undefined}
-- 
cgit v1.2.3-70-g09d2


From 8ceaba8b8264f5519de732cc603dcd276b4b4f4d Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Fri, 28 Jun 2024 01:49:10 -0400
Subject: header text no longer shifts left on hover

---
 src/client/documents/Documents.ts                  |  6 +++++
 src/client/util/Scripting.ts                       |  9 ++++++--
 .../collectionSchema/CollectionSchemaView.scss     |  1 -
 .../collectionSchema/SchemaCellField.tsx           |  4 +++-
 .../collectionSchema/SchemaColumnHeader.tsx        |  6 ++---
 .../collections/collectionSchema/SchemaRowBox.tsx  |  6 +----
 .../collectionSchema/SchemaTableCell.tsx           | 26 +++++++++++++++++-----
 src/client/views/nodes/FieldView.tsx               |  2 +-
 src/client/views/nodes/KeyValueBox.tsx             |  2 +-
 9 files changed, 43 insertions(+), 19 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index dabbf9591..1b1608cd5 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -143,7 +143,12 @@ class ListInfo extends FInfo {
     fieldType? = FInfoFieldType.list;
     values?: List<any>[] = [];
 }
+class MapInfo extends FInfo {
+    fieldType? = FInfoFieldType.list;
+    values?: List<any>[] = [];
+}
 type BOOLt = BoolInfo | boolean;
+type MAPt = MapInfo | Map<any, any>;
 type NUMt = NumInfo | number;
 type STRt = StrInfo | string;
 type LISTt = ListInfo | List<any>;
@@ -229,6 +234,7 @@ export class DocumentOptions {
     _lockedTransform?: BOOLt = new BoolInfo('lock the freeform_panx,freeform_pany and scale parameters of the document so that it be panned/zoomed');
     _childrenSharedWithSchema?: BOOLt = new BoolInfo("whether this document's children are displayed in its parent schema view", false);
     _lockedSchemaEditing?: BOOLt = new BoolInfo("", false);
+    _schemaInputs?: LISTt = new ListInfo('user inputs to schema field', false)
 
     dataViz_title?: string;
     dataViz_line?: string;
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index 6ef592ef2..c7aa56c1e 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -183,14 +183,19 @@ function forEachNode(node: ts.Node, onEnter: Traverser, onExit?: Traverser, inde
     );
 }
 
+ScriptField.CompileScript(value, {}, true, undefined, DocumentIconContainer.getTransformer());
+//addreturn = true
+//capturedvariables = undefined
+//
+
 export function CompileScript(script: string, options: ScriptOptions = {}): CompileResult {
-    const captured = options.capturedVariables ?? {};
+    const captured = options.capturedVariables ?? {}; 
     const signature = Object.keys(captured).reduce((p, v) => {
         const formatCapture = (obj: any) => `${v}=${obj instanceof RefField ? 'XXX' : obj.toString()}`;
         if (captured[v] instanceof Array) return p + (captured[v] as any).map(formatCapture);
         return p + formatCapture(captured[v]);
     }, '');
-    const found = ScriptField.GetScriptFieldCache(script + ':' + signature);
+    const found = ScriptField.GetScriptFieldCache(script + ':' + signature); // if already compiled, found is the result; cache set below
     if (found) return found as CompiledScript;
     const { requiredType = '', addReturn = false, params = {}, capturedVariables = {}, typecheck = true } = options;
     if (options.params && !options.params.this) options.params.this = Doc.name;
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
index 6b53eb1cc..425b67fa9 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss
@@ -155,7 +155,6 @@
     padding: 0;
     z-index: 1;
     border: 1px solid $medium-gray;
-    //overflow: hidden;
 
     .schema-column-title {
         flex-grow: 2;
diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index 27ca37c2b..c7c483df8 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -321,11 +321,13 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         }
     }
 
+    //<FieldView {...this._props.fieldContents}/>
+
     staticDisplay = () => {
         return <span className='editableView-static'>
         {
             // eslint-disable-next-line react/jsx-props-no-spreading
-            this._props.fieldContents ? <FieldView {...this._props.fieldContents} /> : this.props.contents ? this._props.contents?.valueOf() : ''
+            this._props.fieldContents ?  <FieldView {...this._props.fieldContents}/> : ''
         }
         </span>
     }
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index d16cde1f8..83a136737 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -237,11 +237,11 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
                     }}>
                     <div className="schema-column-resizer left" onPointerDown={e => this._props.resizeColumn(e, this._props.columnIndex)} />
 
-                    <div>{this.editableView}</div>
+                    <div className="schema-header-text">{this.editableView}</div>
 
                     <div className="schema-header-menu">
-                        <div className="schema-header-button">
-                            {this.displayButton ? this.headerButton : null}
+                        <div className="schema-header-button" style={{opacity: this.displayButton ? '1.0' : '0.0'}}>
+                            {this.headerButton}
                         </div>
                     </div>  
                 </div>
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index c9feeac6b..077d95c57 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -97,10 +97,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         return ''
     }
 
-    @computed get refSelectModeInfo() {
-        return this.schemaView._referenceSelectMode;
-    }
-
     @computed get menuInfos() {
         const infos: Array<IconProp> = [];
         if (this.Document._lockedSchemaEditing) infos.push('lock');
@@ -178,7 +174,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                     {this.schemaView?.columnKeys?.map((key, index) => (
                         <SchemaTableCell
                             selectReference={this.selectReference}
-                            refSelectModeInfo={this.refSelectModeInfo}
+                            refSelectModeInfo={this.schemaView._referenceSelectMode}
                             eqHighlightFunc={this.eqHighlightFunc}
                             equationHighlightRef={this.schemaView._cellHighlightColors}
                             highlightCells={this.highlightCells}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 016ab5e69..c0e1743a5 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -16,7 +16,7 @@ import { DateField } from '../../../../fields/DateField';
 import { Doc, DocListCast, Field, IdToDoc } from '../../../../fields/Doc';
 import { RichTextField } from '../../../../fields/RichTextField';
 import { ColumnType } from '../../../../fields/SchemaHeaderField';
-import { BoolCast, Cast, DateCast, DocCast, FieldValue, StrCast, toList } from '../../../../fields/Types';
+import { BoolCast, Cast, DateCast, DocCast, FieldValue, ScriptCast, StrCast, toList } from '../../../../fields/Types';
 import { ImageField } from '../../../../fields/URLField';
 import { FInfo, FInfoFieldType } from '../../../documents/Documents';
 import { dropActionType } from '../../../util/DropActionTypes';
@@ -35,6 +35,7 @@ import './CollectionSchemaView.scss';
 import { SchemaColumnHeader } from './SchemaColumnHeader';
 import { ContextMenu } from '../../ContextMenu';
 import { SchemaCellField } from './SchemaCellField';
+import { ComputedField } from '../../../../fields/ScriptField';
 
 export interface SchemaTableCellProps {
     Document: Doc;
@@ -80,6 +81,7 @@ function selectedCell(props: SchemaTableCellProps) {
 export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellProps> {
 
     // private _fieldRef: SchemaCellField | null = null;
+    private _submittedValue: string = '';
 
     constructor(props: SchemaTableCellProps) {
         super(props);
@@ -157,19 +159,31 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
 
     // parses a field from the "idToDoc(####)" format to DocumentId (d#) format for readability
     cleanupField = (field: string) => {
-        const idPattern = /idToDoc\((.*?)\)/g;
         let modField = field.slice();
+        let eqSymbol: string = '';
+        if (modField.startsWith('=')) {modField = modField.substring(1); eqSymbol += '=';}
+        if (modField.startsWith(':=')) {modField = modField.substring(2); eqSymbol += ':=';}
+
+        const idPattern = /idToDoc\((.*?)\)/g;
         let matches;
         let results = new Array<[id: string, func: string]>();
         while ((matches = idPattern.exec(field)) !== null) {results.push([matches[0], matches[1].replace(/"/g, '')]); }
         results.forEach((idFuncPair) => {modField = modField.replace(idFuncPair[0], 'd' + (DocumentView.getDocViewIndex(IdToDoc(idFuncPair[1]))).toString());})
-        if (modField.charAt(modField.length - 1) === ';') modField = modField.substring(0, modField.length - 1);
+
+        for (let i = 0; i < modField.length; ++i){
+            
+        }
+
+        if (modField.endsWith(';')) modField = modField.substring(0, modField.length - 1);
+
+        const inQuotes = (field: string) => {return ((field.startsWith('`') && field.endsWith('`')) || (field.startsWith("'") && field.endsWith("'")) || (field.startsWith('"') && field.endsWith('"')))}
+        if (!inQuotes(this._submittedValue) && inQuotes(modField)) modField = modField.substring(1, modField.length - 1);
         
         const selfRefPattern = `d${this.docIndex}.${this._props.fieldKey}`
         const selfRefRegX = RegExp(selfRefPattern, 'g');
         if (selfRefRegX.exec(modField) !== null) { return 'Invalid'}
 
-        return modField;
+        return eqSymbol + modField;
     }
 
     @computed get defaultCellContent() {
@@ -196,7 +210,8 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                     contents={undefined}
                     fieldContents={fieldProps}
                     editing={selectedCell(this._props) ? undefined : false}
-                    GetValue={() => this.cleanupField(Field.toKeyValueString(fieldProps.Document, this._props.fieldKey, SnappingManager.MetaKey))}
+                    ////const script = ScriptCast(fieldProps.Document[this._props.fieldKey]).rawscript;
+                    GetValue={() => ScriptCast(fieldProps.Document[this._props.fieldKey])?.rawscript ?? ''}
                     SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => {
                         if (shiftDown && enterKey) {
                             this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value);
@@ -205,6 +220,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                         }
                         const hasNoLayout =  Doc.IsDataProto(fieldProps.Document) ? true : undefined; // the "delegate" is a a data document so never write to it's proto
                         const ret = Doc.SetField(fieldProps.Document, this._props.fieldKey.replace(/^_/, ''), value, hasNoLayout);
+                        this._submittedValue = value;
                         this._props.finishEdit?.();
                         return ret;
                     }, 'edit schema cell')}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 818d26956..40da661c0 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -118,7 +118,7 @@ export class FieldView extends React.Component<FieldViewProps> {
         const field = this.fieldval;
         // prettier-ignore
         if (field instanceof Doc)  return <p> <b>{field.title?.toString()}</b></p>;
-        if (field === undefined) return <p>{'<null>'}</p>;
+        if (field === undefined) return <p>{''}</p>;
         if (field instanceof DateField) return <p>{field.date.toLocaleString()}</p>;
         if (field instanceof List) return <div> {field.map(f => Field.toString(f)).join(', ')} </div>;
         if (field instanceof WebField) return <p>{Field.toString(field.url.href)}</p>;
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 66e210c03..bc6633f23 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -88,7 +88,7 @@ export class KeyValueBox extends ViewBoxBaseComponent<FieldViewProps>() {
         const type: 'computed' | 'script' | false = rawvalue.startsWith(':=') ? 'computed' : rawvalue.startsWith('$=') ? 'script' : false;
         rawvalue = type ? rawvalue.substring(2) : rawvalue;
         rawvalue = rawvalue.replace(/.*\(\((.*)\)\)/, 'dashCallChat(_setCacheResult_, this, `$1`)');
-        const value = ["'", '"', '`'].includes(rawvalue.length ? rawvalue[0] : '') || !isNaN(rawvalue as any) ? rawvalue : '`' + rawvalue + '`';
+        const value = (["'", '"', '`'].includes(rawvalue.length ? rawvalue[0] : '') || !isNaN(rawvalue as any)) ? rawvalue : '`' + rawvalue + '`';
 
         let script = ScriptField.CompileScript(rawvalue, {}, true, undefined, DocumentIconContainer.getTransformer());
         if (!script.compiled) {
-- 
cgit v1.2.3-70-g09d2


From b01f8732034396114c6a37665054de1617ccda1b Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Fri, 28 Jun 2024 14:32:27 -0400
Subject: fixed selected row highlight on new col

---
 src/client/views/collections/collectionSchema/SchemaRowBox.tsx    | 5 +----
 src/client/views/collections/collectionSchema/SchemaTableCell.tsx | 5 +----
 2 files changed, 2 insertions(+), 8 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 077d95c57..9ac7a24b2 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -90,10 +90,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
     }
 
     @computed get menuBackgroundColor(){
-        if (this.Document._lockedSchemaEditing){
-            if (this._props.isSelected()) return '#B0D1E7'
-            else return '#F5F5F5'
-        }   
+        if (this.Document._lockedSchemaEditing) {return '#F5F5F5'}   
         return ''
     }
 
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index d06e2a147..084306c4a 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -94,10 +94,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
     get lockedInteraction(){return (this.isDefault || this._props.Document._lockedSchemaEditing);} // prettier-ignore
 
     get backgroundColor(){
-        if (this.lockedInteraction){
-            if (this._props.rowSelected()) return '#B0D1E7'
-            else return '#F5F5F5'
-        }   
+        if (this.lockedInteraction) {return '#F5F5F5'}   
         return ''
     }
 
-- 
cgit v1.2.3-70-g09d2


From 3dd0a92767972736f415341c0b6e06e6e3a242b1 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Mon, 1 Jul 2024 16:38:24 -0400
Subject: highlighting then un-highlighting a selected cell with equations now
 properly maintains original select highlight

---
 src/client/views/EditableView.tsx                     |  1 -
 .../collectionSchema/CollectionSchemaView.tsx         | 19 +++++++++++++++----
 .../collections/collectionSchema/SchemaCellField.tsx  |  8 ++++++--
 .../collections/collectionSchema/SchemaRowBox.tsx     | 13 ++-----------
 .../collections/collectionSchema/SchemaTableCell.tsx  | 10 +++-------
 5 files changed, 26 insertions(+), 25 deletions(-)

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

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 0c09e12de..af6a43555 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -206,7 +206,6 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
     
     @action
     finalizeEdit(value: string, shiftDown: boolean, lostFocus: boolean, enterKey: boolean) {
-        //if (invalid) raise error
         if (this._props.SetValue(value, shiftDown, enterKey)) {
             this._editing = false;
             this._props.isEditingCallback?.(false);
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 7a90b3505..b81cfa821 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -606,12 +606,24 @@ export class CollectionSchemaView extends CollectionSubView() {
         return cells;
     }
 
+    selectionOverlap = (doc: Doc): [boolean, boolean] => {
+        const docs = this.docsWithDrag.docs;
+        const index = this.rowIndex(doc);
+        const selectedBelow: boolean = this._selectedDocs.includes(docs[index + 1]);
+        const selectedAbove: boolean = this._selectedDocs.includes(docs[index - 1]);
+        return [selectedAbove, selectedBelow];
+    }
+
     removeCellHighlights = () => {
         this._highlightedCellsInfo.forEach(info => {
             const doc = info[0];
             const field = info[1];
             const cell = this.getCellElement(doc, field);
-            if (!(this._selectedDocs.includes(doc) && this._selectedCol === this.columnKeys.indexOf(field))) cell.style.border = ''; 
+            if (this._selectedDocs.includes(doc) && this._selectedCol === this.columnKeys.indexOf(field)) {
+                cell.style.border = `solid 2px ${Colors.MEDIUM_BLUE}`;
+                if (this.selectionOverlap(doc)[0]) cell.style.borderTop = '';
+                if (this.selectionOverlap(doc)[1]) cell.style.borderBottom = '';
+            } else cell.style.border = '';
             cell.style.backgroundColor = '';});
         this._highlightedCellsInfo = [];
     }
@@ -741,7 +753,6 @@ export class CollectionSchemaView extends CollectionSubView() {
 
     @action
     onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
-        console.log('called')
         if (de.complete.columnDragData) {
             setTimeout(() => {this.setColDrag(false);});
             e.stopPropagation();
@@ -881,8 +892,8 @@ export class CollectionSchemaView extends CollectionSubView() {
         this.closeColumnMenu();
     };
 
-    setColumnValues = (key: string, value: string) => {
-        if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing &&Doc.SetField(doc, key, value)); 
+    setCellValues = (key: string, value: string) => {
+        if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); 
         else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); 
         return true;
     };
diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index c7c483df8..e1059b8fc 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -95,7 +95,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             () => this._props.GetValue(),
             fieldVal => {
                 this._unrenderedContent = fieldVal ?? '';
-                this.setContent(this._unrenderedContent);
+                this.finalizeEdit(false, false, false);
             }
         )
     }
@@ -246,6 +246,10 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
     @action
     onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
         if (e.nativeEvent.defaultPrevented) return; // hack .. DashFieldView grabs native events, but react ignores stoppedPropagation and preventDefault, so we need to check it here
+        // if (e.metaKey) {
+        //     e.stopPropagation();
+        //     e.preventDefault();
+        // }
         switch (e.key) {
             case 'Tab':
                 e.stopPropagation();
@@ -302,7 +306,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
     finalizeEdit(shiftDown: boolean, lostFocus: boolean, enterKey: boolean) {
         if (this._unrenderedContent.replace(this.selfRefPattern, '') !== this._unrenderedContent) {
             this._dependencyMessageShown ? this._dependencyMessageShown = false :
-            alert("Circular dependency detected. Please update the field.")
+            alert(`Circular dependency detected. Please update the field at ${this.selfRefPattern}.`)
             this._dependencyMessageShown = true;
             return;
         }
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 9ac7a24b2..2410b2793 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -101,23 +101,14 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         return infos;
     }
 
-    @computed get isolatedSelection() {
-        const toReturn: [boolean, boolean] = [true, true];
-        const docs = this.schemaView.docsWithDrag.docs;
-        const selectedBelow: boolean = this.schemaView?._selectedDocs.includes(docs[this.rowIndex + 1]);
-        const selectedAbove: boolean = this.schemaView?._selectedDocs.includes(docs[this.rowIndex - 1]);
-        toReturn[0] = selectedAbove;
-        toReturn[1] = selectedBelow;
-        return toReturn;
-    }
-
+    isolatedSelection = (doc: Doc) => {return this.schemaView?.selectionOverlap(doc)};
     setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY);
     selectedCol = () => this.schemaView._selectedCol;
     getFinfo = computedFn((fieldKey: string) => this.schemaView?.fieldInfos.get(fieldKey));
     selectCell = (doc: Doc, col: number, shift: boolean, ctrl: boolean) => this.schemaView?.selectCell(doc, col, shift, ctrl);
     deselectCell = () => this.schemaView?.deselectAllCells();
     selectedCells = () => this.schemaView?._selectedDocs;
-    setColumnValues = (field: any, value: any) => this.schemaView?.setColumnValues(field, value) ?? false;
+    setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false;
     columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
     computeRowIndex = () => this.schemaView?.rowIndex(this.Document);
     highlightCells = (text: string) => this.schemaView?.highlightCells(text);
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 1f5684151..e2a05da7f 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -60,7 +60,7 @@ export interface SchemaTableCellProps {
     autoFocus?: boolean; // whether to set focus on creation, othwerise wait for a click
     rootSelected?: () => boolean;
     rowSelected: () => boolean;
-    isolatedSelection: [boolean, boolean];
+    isolatedSelection: (doc: Doc) => [boolean, boolean];
     highlightCells: (text: string) => void;
     equationHighlightRef: ObservableMap<HTMLDivElement, string>;
     eqHighlightFunc: (text: string) => HTMLDivElement[] | [];
@@ -174,10 +174,6 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
 
         const inQuotes = (field: string) => {return ((field.startsWith('`') && field.endsWith('`')) || (field.startsWith("'") && field.endsWith("'")) || (field.startsWith('"') && field.endsWith('"')))}
         if (!inQuotes(this._submittedValue) && inQuotes(modField)) modField = modField.substring(1, modField.length - 1);
-        
-        const selfRefPattern = `d${this.docIndex}.${this._props.fieldKey}`
-        const selfRefRegX = RegExp(selfRefPattern, 'g');
-        if (selfRefRegX.exec(modField) !== null) { return 'Invalid'}
 
         return eqSymbol + modField;
     }
@@ -255,8 +251,8 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         const sides: Array<string | undefined> = [];
         sides[0] = selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // left
         sides[1] = selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // right
-        sides[2] = (!this._props.isolatedSelection[0] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // top
-        sides[3] = (!this._props.isolatedSelection[1] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // bottom
+        sides[2] = (!this._props.isolatedSelection(this._props.Document)[0] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // top
+        sides[3] = (!this._props.isolatedSelection(this._props.Document)[1] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // bottom
         return sides;
     }
 
-- 
cgit v1.2.3-70-g09d2


From 1447bae0e24016f0c4fde772235d3e60f2b3555c Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Fri, 12 Jul 2024 14:44:48 -0400
Subject: basic doc creation from templates working

---
 .../collections/collectionSchema/SchemaRowBox.tsx  |  3 +-
 src/client/views/nodes/DataVizBox/DataVizBox.tsx   | 51 +++++++++++++---
 .../views/nodes/DataVizBox/DocCreatorMenu.tsx      | 68 ++++++++++++++++------
 3 files changed, 95 insertions(+), 27 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 2410b2793..72f5d8c25 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -24,6 +24,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { infoState } from '../collectionFreeForm/CollectionFreeFormInfoState';
 import { TbShieldX } from 'react-icons/tb';
+import { DocumentType } from '../../../documents/DocumentTypes';
 
 interface SchemaRowBoxProps extends FieldViewProps {
     rowIndex: number;
@@ -77,7 +78,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
             icon: 'minus',
         });
         const childDocs = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)])
-        if (this.Document.type === 'collection' && childDocs.length) {
+        if (childDocs.length) {
                 ContextMenu.Instance.addItem({
                 description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema',
                 event: () => {
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index c43177c51..86a9db79c 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -5,14 +5,14 @@ import { Colors, Toggle, ToggleType, Type } from 'browndash-components';
 import { IReactionDisposer, ObservableMap, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { returnEmptyString, returnFalse, returnOne, setupMoveUpEvents } from '../../../../ClientUtils';
+import { ClientUtils, returnEmptyString, returnFalse, returnOne, setupMoveUpEvents } from '../../../../ClientUtils';
 import { emptyFunction } from '../../../../Utils';
-import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../../fields/Doc';
+import { Doc, DocListCast, Field, FieldType, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
 import { InkTool } from '../../../../fields/InkField';
 import { List } from '../../../../fields/List';
 import { Cast, CsvCast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
 import { CsvField } from '../../../../fields/URLField';
-import { TraceMobx } from '../../../../fields/util';
+import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util';
 import { DocUtils } from '../../../documents/DocUtils';
 import { DocumentType } from '../../../documents/DocumentTypes';
 import { Docs } from '../../../documents/Documents';
@@ -33,8 +33,10 @@ import { LineChart } from './components/LineChart';
 import { PieChart } from './components/PieChart';
 import { TableBox } from './components/TableBox';
 import { LinkManager } from '../../../util/LinkManager';
-import { Collection } from 'mongoose';
-import { DocCreatorMenu } from './DocCreatorMenu';
+import { DataVizTemplateInfo, DocCreatorMenu } from './DocCreatorMenu';
+import { CollectionFreeFormView } from '../../collections/collectionFreeForm';
+import { PrefetchProxy } from '../../../../fields/Proxy';
+import { AclAdmin, AclAugment, AclEdit } from '../../../../fields/DocSymbols';
 
 export enum DataVizView {
     TABLE = 'table',
@@ -149,6 +151,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         // }
         // return func() ?? false;
     };
+
     getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
         const visibleAnchor = AnchorMenu.Instance.GetAnchor?.(undefined, addAsAnnotation);
         const anchor = !pinProps
@@ -457,7 +460,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
 
     getPossibleTemplates = (): Doc[] => {
         const linkedDocs: Doc[] = LinkManager.Instance.getAllRelatedLinks(this.Document).map(d => DocCast(LinkManager.getOppositeAnchor(d, this.Document)));
-        const linkedCollections: Doc[] = linkedDocs.filter(doc => doc.type === 'config').filter(doc => DocCast(doc.annotationOn).type === 'collection').map(doc => DocCast(doc.annotationOn));
+        const linkedCollections: Doc[] = linkedDocs.filter(doc => doc.type === 'config').map(doc => DocCast(doc.annotationOn));
         const isColumnTitle = (title: string): boolean => {
             const colTitles: string[] = Object.keys(this.records[0]);
             for (let i = 0; i < colTitles.length; ++i){
@@ -470,7 +473,6 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         }
         const isValidTemplate = (collection: Doc) => {
             const childDocs = DocListCast(collection[Doc.LayoutFieldKey(collection)]);
-            console.log('childDocs of col: ' + childDocs)
             for (let i = 0; i < childDocs.length; ++i){
                 if (isColumnTitle(String(childDocs[i].title))) return true;
             }
@@ -479,6 +481,41 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         return linkedCollections.filter(col => isValidTemplate(col));
     }
 
+    ApplyTemplateTo = (templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined) => {
+        if (!Doc.AreProtosEqual(target[targetKey] as Doc, templateDoc)) {
+            if (target.resolvedDataDoc) {
+                target[targetKey] = new PrefetchProxy(templateDoc);
+            } else {
+                titleTarget && (Doc.GetProto(target).title = titleTarget);
+                const setDoc = [AclAdmin, AclEdit, AclAugment].includes(GetEffectiveAcl(Doc.GetProto(target))) ? Doc.GetProto(target) : target;
+                setDoc[targetKey] = new PrefetchProxy(templateDoc);
+            }
+        }
+        return target;
+    }
+
+    @action
+    createDocsFromTemplate = (templateInfo: DataVizTemplateInfo) => {
+        const mainCollection = this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView;
+        const fields: string[] = Array.from(Object.keys(this.records[0])); 
+        const selectedRows = NumListCast(this.layoutDoc.dataViz_selectedRows);
+        const docs: Doc[] = selectedRows.map(row => {
+            const values: String[] = [];
+            fields.forEach(col => values.push(this.records[row][col]));
+
+            const proto = new Doc();
+            proto.author = ClientUtils.CurrentUserEmail();
+            values.forEach((val, i) => {proto[fields[i]] = val as FieldType});
+            
+            const target = Doc.MakeDelegate(proto);
+            const targetKey = StrCast(templateInfo.doc.layout_fieldKey, 'layout');
+            const applied = this.ApplyTemplateTo(templateInfo.doc, target, targetKey, templateInfo.doc.title + `${row}`);
+            target.layout_fieldKey = targetKey;
+            return applied;
+        });
+        docs.forEach(doc => mainCollection.addDocument(doc));
+    }
+
     /**
      * creates a new dataviz document filter from this one
      *      it appears to the right of this document, with the
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
index 3ebf97570..88308c226 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
@@ -2,7 +2,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { IReactionDisposer, ObservableMap, action, makeObservable, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils';
+import { returnAll, returnFalse, setupMoveUpEvents } from '../../../../ClientUtils';
 import { Doc } from '../../../../fields/Doc';
 import { DocCast, ImageCast } from '../../../../fields/Types';
 import { ImageField } from '../../../../fields/URLField';
@@ -15,6 +15,15 @@ import { DataVizBox } from './DataVizBox';
 import './DocCreatorMenu.scss';
 import { Id } from '../../../../fields/FieldSymbols';
 import { Colors } from 'browndash-components';
+import { MakeTemplate } from '../../../util/DropConverter';
+
+export enum LayoutType {
+    Stacked = 'stacked', 
+    Grid = 'grid', 
+    Row = 'row', 
+    Column = 'column', 
+    Custom = 'custom'
+}
 
 @observer
 export class DocCreatorMenu extends ObservableReactComponent<{}> {
@@ -25,9 +34,9 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
 
     @observable _templateDocs: Doc[] = [];
     @observable _templateRefToDoc?: ObservableMap<HTMLDivElement, Doc>;
-    @observable _selectedTemplateID?: Doc;
+    @observable _selectedTemplate?: Doc;
 
-    @observable _selectedLayout?: 'stacked' | 'grid' | 'row' | 'column' | 'custom';
+    @observable _selectedLayout?: LayoutType;
 
     @observable _pageX: number = 0;
     @observable _pageY: number = 0;
@@ -49,9 +58,8 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
     }
 
     @action setDataViz = (dataViz: DataVizBox) => { this._dataViz = dataViz };
-    @action setTemplateDocs = (docs: Doc[]) => {
-         this._templateDocs = docs.map(doc => doc.annotationOn ? DocCast(doc.annotationOn):doc);
-    };
+    @action setTemplateDocs = (docs: Doc[]) => {this._templateDocs = docs.map(doc => doc.annotationOn ? DocCast(doc.annotationOn):doc)};
+
 
     @action
     onPointerDown = (e: PointerEvent) => {
@@ -126,17 +134,22 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
                 {this._templateDocs.map(doc => ({icon: ImageCast(doc.icon), doc})).filter(info => info.icon && info.doc).map(info => {
                     if (renderedTemplates.includes(info.doc)) return undefined;
                     renderedTemplates.push(info.doc);
+                    //let ref: any = undefined;
                     return (<div 
+                    //ref={r => ref = r}
                     className='docCreatorMenu-preview-window'
                     style={{
-                        background: this._selectedTemplateID === info.doc ? Colors.MEDIUM_BLUE : '',
-                        boxShadow: this._selectedTemplateID === info.doc ? `0 0 15px rgba(68, 118, 247, .8)` : ''
+                        background: this._selectedTemplate === info.doc ? Colors.MEDIUM_BLUE : '',
+                        boxShadow: this._selectedTemplate === info.doc ? `0 0 15px rgba(68, 118, 247, .8)` : ''
                     }}
                     onPointerDown={e =>
                         setupMoveUpEvents(this, e, returnFalse, emptyFunction,
                             undoable(clickEv => {
                                 clickEv.stopPropagation();
-                                this._selectedTemplateID = info.doc;
+                                this._selectedTemplate = info.doc;
+                                MakeTemplate(info.doc);
+                                // ref.style.background = Colors.MEDIUM_BLUE;
+                                // ref.style.boxShadow = `0 0 15px rgba(68, 118, 247, .8)`;
                                 this.forceUpdate();
                             }, 'open actions menu')
                         )
@@ -150,7 +163,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
 
     get optionsMenuContents(){
 
-        const layoutOption = (option: 'stacked' | 'grid' | 'row' | 'column' | 'custom', optStyle?: {}) => {
+        const layoutOption = (option: LayoutType, optStyle?: {}) => {
             return (
                 <div 
                     className="docCreatorMenu-dropdown-option" 
@@ -173,11 +186,11 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
                 <div className='docCreatorMenu-dropdown-hoverable'>
                     <div className="docCreatorMenu-dropdown-title">Choose Layout</div>
                     <div className="docCreatorMenu-dropdown-content">
-                        {layoutOption('stacked')}
-                        {layoutOption('grid')}
-                        {layoutOption('row')}
-                        {layoutOption('column')}
-                        {layoutOption('custom', {borderBottom: `0px`})}
+                        {layoutOption(LayoutType.Stacked)}
+                        {layoutOption(LayoutType.Grid)}
+                        {layoutOption(LayoutType.Row)}
+                        {layoutOption(LayoutType.Column)}
+                        {layoutOption(LayoutType.Custom, {borderBottom: `0px`})}
                     </div>
                 </div>
                 <div className='docCreatorMenu-layout-preview-window'>
@@ -242,7 +255,22 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
                         >
                             <FontAwesomeIcon icon={this._menuContent === 'templates' ? 'bars' : 'magnifying-glass'}/>
                         </button>
-                        <button className='docCreatorMenu-menu-button right'>
+                        <button 
+                        className='docCreatorMenu-menu-button right'
+                        onPointerDown={e =>
+                            setupMoveUpEvents(
+                                this,
+                                e,
+                                returnFalse,
+                                emptyFunction,
+                                undoable(clickEv => {
+                                    clickEv.stopPropagation();
+                                    if (!this._selectedTemplate) return;
+                                    const templateInfo: DataVizTemplateInfo = {doc: this._selectedTemplate};
+                                    this._dataViz?.createDocsFromTemplate(templateInfo);
+                                }, 'make docs')
+                            )
+                        }>
                             <FontAwesomeIcon icon={'plus'}/>
                         </button>
                         <button 
@@ -258,8 +286,7 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
                                         this.closeMenu();
                                     }, 'close menu')
                                 )
-                            }
-                        >
+                            }>
                             <FontAwesomeIcon icon={'minus'}/>
                         </button>
                     </div>
@@ -270,6 +297,9 @@ export class DocCreatorMenu extends ObservableReactComponent<{}> {
             </div>
             )
         }
-    
+}
 
+export interface DataVizTemplateInfo {
+    doc: Doc;
+    layout?: LayoutType;
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From e7235baa7ed998908dec8bf48e4c244594aa76bb Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Sun, 8 Sep 2024 18:42:12 -0400
Subject: schema changes reverted

---
 .../collectionSchema/CollectionSchemaView.tsx      |   3 +-
 .../collectionSchema/SchemaCellField.tsx           | 123 +--------------------
 .../collectionSchema/SchemaColumnHeader.tsx        |   2 +-
 .../collections/collectionSchema/SchemaRowBox.tsx  |   5 +-
 .../collectionSchema/SchemaTableCell.tsx           |   2 +-
 .../views/nodes/DataVizBox/DocCreatorMenu.tsx      |   9 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |   2 +-
 7 files changed, 16 insertions(+), 130 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 12c342b9f..59ccec71f 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -46,7 +46,6 @@ import { SchemaCellField } from './SchemaCellField';
 import { threadId } from 'worker_threads';
 import { FontIconBox } from '../../nodes/FontIconBox/FontIconBox';
 
-// eslint-disable-next-line @typescript-eslint/no-var-requires
 const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore
 
 export const FInfotoColType: { [key: string]: ColumnType } = {
@@ -1539,4 +1538,4 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP
             </div>
         );
     }
-}
+}
\ No newline at end of file
diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index 3be9167fe..e1059b8fc 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -8,15 +8,6 @@ import { FieldView, FieldViewProps } from "../../nodes/FieldView";
 import { ObjectField } from "../../../../fields/ObjectField";
 import { Doc } from "../../../../fields/Doc";
 import { DocumentView } from "../../nodes/DocumentView";
-import { date } from "serializr";
-import { createRoot } from "react-dom/client";
-import DatePicker from "react-datepicker";
-import { emptyFunction } from "../../../../Utils";
-import { DateField } from "../../../../fields/DateField";
-
-enum EleType {
-    plainText, fieldReference, date, boolean
-}
 
 export interface SchemaCellFieldProps {
     contents: any;
@@ -43,7 +34,6 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
     @observable _displayedContent = '';
     @observable _inCellSelectMode: boolean = false;
     @observable _dependencyMessageShown: boolean = false;
-    @observable _displayedElements: JSX.Element[] = [];
 
     constructor(props: SchemaCellFieldProps) {
         super(props);
@@ -126,32 +116,12 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         this.finalizeEdit(false, true, false);
     }
 
-    // addReactComponents = () => {
-    //     if (!this._inputref) return;
-
-    //     const dateRefs = Array.from(this._inputref.querySelectorAll('.date-placeholder'));
-
-    //     dateRefs.forEach(ref => {
-    //         const root = createRoot(ref);
-    //         root.render(<DatePicker dateFormat="Pp" selected={new Date} onChange={emptyFunction} />);
-    //     })
-    // }
-
-    generateSpan = (text: string, cell: HTMLDivElement | undefined): JSX.Element => {
+    generateSpan = (text: string, cell: HTMLDivElement | undefined) => {
         const selfRef = text === this.selfRefPattern;
-        const color: string | undefined = cell?.style.borderTop.replace('2px solid', '');
-        return (
-            <span style={{
-                textDecoration: selfRef ? 'underline' : 'none', 
-                textDecorationColor: 'red', 
-                color: selfRef ? 'gray' : color}}>
-                {text}
-            </span>
-        );
+        return `<span style="text-decoration: ${selfRef ? 'underline' : 'none'}; text-decoration-color: red; color: ${selfRef ? 'gray' : cell?.style.borderTop.replace('2px solid', '')}">${text}</span>`;
     }
 
     makeSpans = (content: string) => {
-        const spans: JSX.Element[] = [];
         let chunkedText = content;
 
         const pattern = /(this|d(\d+))\.(\w+)/g;
@@ -170,93 +140,17 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
 
         let matchNum = 0;
         matches.forEach((match: string) => {
-            chunkedText = chunkedText.replace(match, '');
-            spans.push(this.generateSpan(match, cells.get(match)));
+            chunkedText = chunkedText.replace(match, this.generateSpan(match, cells.get(match)));
             ++matchNum;
         })
 
-        chunkedText = chunkedText.replace(/{{date}}/g, `<span class="date-placeholder">placeholder text</span>`);
-
         return chunkedText;
     }
 
-    verifyCellRef = (text: string): [string, HTMLDivElement | undefined] | undefined => {
-        const pattern = /(this|d(\d+))\.(\w+)/g;
-        let matchedText: string = '';
-        let matchedCell: HTMLDivElement | undefined = undefined; 
-        let match: RegExpExecArray | null;
-
-        while ((match = pattern.exec(text)) !== null) {
-            const cells = this._props.getCells(match[0]);
-            if (cells.length) {
-                matchedText = match[0];
-                matchedCell = cells[0];
-            }
-        }
-
-        if (!matchedText && !matchedCell) return undefined;
-        else return [matchedText, matchedCell];
-    }
-
-    elementsFromText = (chunks: string[]): JSX.Element[] => {
-        const eles: any[] = [];
-
-        chunks.forEach(text => {
-            const cellRef = this.verifyCellRef(text);
-            if (cellRef) {
-                eles.push(this.generateSpan(cellRef[0], cellRef[1]));
-            } else if (text && !text.replace('{{date}}', '')){
-                eles.push(<DatePicker dateFormat="Pp" selected={new Date()} onChange={emptyFunction} />);
-            } else if (text && !text.replace('{{boolean}}', '')) {
-                eles.push(<span>boolean thing</span>);
-            } else {
-                eles.push(<span>{text}</span>);
-            }
-        });
-
-        return eles;
-    }
-
-    parseElements = (content: string) => {
-        let string: string = content;
-        if (string.startsWith(':')) string = string.slice(1);
-        if (string.startsWith('=')) string = string.slice(1);
-
-        const chunks: string[] = [];
-
-        let subStr: string = '';
-        let currChar = '';
-        for (let i = 0; i < string.length; i++){
-            currChar = string[i];
-            if (((string.charCodeAt(i) === 32 || string.charCodeAt(i) === 160) && subStr.trim()) || (currChar !== ' ' && !subStr.trim())) {
-                chunks.push(subStr);
-                subStr = currChar;
-            } else {
-                subStr += currChar;
-            }
-        }
-
-        if (subStr) {chunks.push(subStr)};
-
-        return this.elementsFromText(chunks);
-    }
-
-    // `<input
-    //     style={{ marginRight: 4 }}
-    //     type="checkbox"
-    //     checked={BoolCast(this._props.Document[this._props.fieldKey])}
-    //     onChange={undoBatch((value: React.ChangeEvent<HTMLInputElement> | undefined) => {
-    //         if ((value?.nativeEvent as any).shiftKey) {
-    //             this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + (value?.target?.checked.toString() ?? ''));
-    //         } else Doc.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + (value?.target?.checked.toString() ?? ''));
-    //     })}
-    // />`
-
     @action 
     setContent = (content: string, restoreCursorPos?: boolean) => {
         const pos = this.cursorPosition;
-        this._displayedContent = content;
-        this._displayedElements = this.parseElements(content);
+        this._displayedContent = this.makeSpans(content);
         restoreCursorPos && setTimeout(() => this.setCursorPosition(pos));
     }
 
@@ -339,9 +233,8 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         }
         this._unrenderedContent = targVal;
         this._props.highlightCells?.(targVal);
-        if (this.parseElements(targVal).length > this.parseElements(this._displayedContent).length) this.setContent(targVal, true);
+        if (this.shouldUpdate(prevVal, targVal)) {this.setContent(targVal, true)};
         this.setupRefSelect(this.refSelectConditionMet);
-        console.log(this.parseElements(targVal));
     };
 
     setupRefSelect = (enabled: boolean) => {
@@ -458,12 +351,8 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             onClick={e => e.stopPropagation}
             onPointerUp={e => e.stopPropagation}
             onPointerMove={e => {e.stopPropagation(); e.preventDefault()}}
-            suppressContentEditableWarning={true}
-            //dangerouslySetInnerHTML={{ __html: this._displayedContent }}
+            dangerouslySetInnerHTML={{ __html: this._displayedContent }}
             >
-                {this._displayedElements.map((ele, index) => {
-                    return <span key={index}>{ele}</span>;
-                })}
             </div>
         );
     }
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 40509c41b..9f6478041 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -249,4 +249,4 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
                 </div>
         );
     }
-}
+}
\ No newline at end of file
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index 72f5d8c25..ec94a8077 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -24,7 +24,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { infoState } from '../collectionFreeForm/CollectionFreeFormInfoState';
 import { TbShieldX } from 'react-icons/tb';
-import { DocumentType } from '../../../documents/DocumentTypes';
 
 interface SchemaRowBoxProps extends FieldViewProps {
     rowIndex: number;
@@ -78,7 +77,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
             icon: 'minus',
         });
         const childDocs = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)])
-        if (childDocs.length) {
+        if (this.Document.type === 'collection' && childDocs.length) {
                 ContextMenu.Instance.addItem({
                 description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema',
                 event: () => {
@@ -197,4 +196,4 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
             </div>
         );
     }
-}
+}
\ No newline at end of file
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 7d29e40cc..e2a05da7f 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -389,7 +389,7 @@ export class SchemaDateCell extends ObservableReactComponent<SchemaTableCellProp
         const { pointerEvents } = SchemaTableCell.renderProps(this._props);
         return (
             <>
-                <div style={{ pointerEvents: 'none'}}>
+                <div style={{ pointerEvents: 'none' }}>
                     <DatePicker dateFormat="Pp" selected={this.date?.date ?? Date.now()} onChange={emptyFunction} />
                 </div>
                 {pointerEvents === 'none' ? null : (
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
index dcdd52c73..8273f3e09 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
@@ -375,7 +375,6 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
 
             if (res && this._callCount === origCount) {
                 this._suggestedTemplates = [];
-                this._GPTLoading = false;
                 const templates: {template_type: string, fieldVals: {title: string, tlx: string, tly: string, brx: string, bry: string}[]}[] = JSON.parse(res);
                 this.createGeneratedTemplates(templates, 500, 500);
             }
@@ -714,7 +713,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
                 try {
                     const renderedImages: Doc[] = await Promise.all(
                         calls.map(async ([fieldNum, col]) => {
-                            const sysPrompt = 'Your job is to create a prompt for an AI image generator to help it generate an image based on existing content in a template and a user prompt. ONLY INCLUDE THE PROMPT, NO OTHER TEXT OR EXPLANATION. The existing content is as follows: ' + fieldContent + ' **** The user prompt is: ' + col.desc;
+                            const sysPrompt = 'Your job is to create a prompt for an AI image generator to help it generate an image based on existing content in a template and a user prompt. Your prompt should focus heavily on visual elements to help the image generator; avoid unecessary info that might distract it. ONLY INCLUDE THE PROMPT, NO OTHER TEXT OR EXPLANATION. The existing content is as follows: ' + fieldContent + ' **** The user prompt is: ' + col.desc;
                             
                             const prompt = await gptAPICall(sysPrompt, GPTCallType.COMPLETEPROMPT);
                             console.log(sysPrompt, prompt);
@@ -852,7 +851,6 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
             const res = await gptAPICall(prompt, GPTCallType.TEMPLATE);
 
             if (res && this._callCount === origCount) {
-                this._GPTLoading = false;
 
                 const assignments: {[templateTitle: string]: {[field: string]: string}} = JSON.parse(res);
                 const brokenDownAssignments: [TemplateDocInfos, {[field: number]: Col}][] = [];
@@ -889,7 +887,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
     
         const renderedTemplates: Doc[] = await Promise.all(renderedTemplatePromises);
         
-        setTimeout(() => { this.setGSuggestedTemplates(renderedTemplates) });
+        setTimeout(() => { this.setGSuggestedTemplates(renderedTemplates); this._GPTLoading = false });
     };
 
     @action setExpandedView = (info: {icon: ImageField, doc: Doc} | undefined) => {
@@ -908,6 +906,7 @@ export class DocCreatorMenu extends ObservableReactComponent<FieldViewProps> {
             <div className={`docCreatorMenu-templates-view`}>
                 {this._expandedPreview ? 
                 <div className='docCreatorMenu-expanded-template-preview'>
+                    <img className='docCreatorMenu-preview-image expanded' src={this._expandedPreview.icon!.url.href.replace(".png", "_o.png")} />
                     <div className='right-buttons-panel'>
                         <button className='docCreatorMenu-menu-button section-reveal-options top-right' onPointerDown={e => this.setUpButtonClick(e, () => this.setExpandedView(undefined))}> 
                             <FontAwesomeIcon icon='minimize'/>
@@ -1618,7 +1617,7 @@ export class FieldFuncs {
             _rotation: opts.rotation,
         });
 
-        //setTimeout(() => {console.log('called', RichTextMenu.Instance), RichTextMenu.Instance?.setFontField('#4CE4D4', 'fontColor')}, 2000);
+        docWithBasicOpts._layout_hideScroll = true;
 
         return docWithBasicOpts;
     }
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 54e6c0add..e091657a8 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -2100,7 +2100,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
                         }}
                         style={{
                             width: this.noSidebar ? '100%' : `calc(100% - ${this.layout_sidebarWidthPercent})`,
-                            overflow: this.layoutDoc._createDocOnCR ? 'hidden' : this.layoutDoc._layout_autoHeight ? 'visible' : undefined,
+                            overflow: this.layoutDoc._createDocOnCR || this.layoutDoc._layout_hideScroll ? 'hidden' : this.layout_autoHeight ? 'visible' : undefined,
                         }}
                         onScroll={this.onScroll}
                         onDrop={this.ondrop}>
-- 
cgit v1.2.3-70-g09d2


From d8a43b76f101a2f38ef1e3e9cbf8ec036468481d Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Sun, 22 Sep 2024 15:29:28 -0400
Subject: header comments + change to cellfield updating

---
 .../collectionSchema/CollectionSchemaView.tsx      | 22 +++++++++-
 .../collectionSchema/SchemaCellField.tsx           | 48 +++++++++++++++-------
 .../collectionSchema/SchemaColumnHeader.tsx        |  6 +--
 .../collections/collectionSchema/SchemaRowBox.tsx  | 11 ++---
 .../collectionSchema/SchemaTableCell.tsx           | 15 ++++---
 5 files changed, 69 insertions(+), 33 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 0e5a1e6b6..11a4e88f9 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -495,6 +495,26 @@ export class CollectionSchemaView extends CollectionSubView() {
         return adjIndex;
     };
 
+    @action
+    setRelCursorIndex = (mouseY: number) => {
+        this._mouseCoordinates.y = mouseY; // updates this.rowDropIndex computed value to overwrite the old cached value
+
+        const rowHeight = CollectionSchemaView._rowHeight;
+        const adjInitMouseY = mouseY - rowHeight - 100; // rowHeight: height of the column menu cells | 100: height of the top menu
+        const yOffset = this._lowestSelectedIndex * rowHeight;
+
+        const heights = this._selectedDocs.map(() => this.rowHeightFunc());
+        let index: number = 0;
+        heights.reduce((total, curr, i) => {
+            if (total <= adjInitMouseY && total + curr >= adjInitMouseY) {
+                if (adjInitMouseY <= total + curr) index = i;
+                else index = i + 1;
+            }
+            return total + curr;
+        }, yOffset);
+        this._relCursorIndex = index;
+    };
+
     highlightDraggedColumn = (index: number) =>
         this._colEles.forEach((colRef, i) => {
             const edgeStyle = i === index ? `solid 2px ${Colors.MEDIUM_BLUE}` : '';
@@ -731,7 +751,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         const field = this.columnKeys[col];
         const refToAdd = `d${docIndex}.${field}`
         const editedField = this._referenceSelectMode.currEditing ? this._referenceSelectMode.currEditing as SchemaCellField : null;
-        editedField?.appendText(refToAdd, true);
+        editedField?.insertText(refToAdd, true);
         editedField?.setupRefSelect(false);
         return;
     }
diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index 1ee79fa0b..72dcc00e6 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -9,6 +9,16 @@ import { ObjectField } from "../../../../fields/ObjectField";
 import { Doc } from "../../../../fields/Doc";
 import { DocumentView } from "../../nodes/DocumentView";
 
+/**
+ * The SchemaCellField renders text in schema cells while the user is editing, and updates the
+ * contents of the field based on user input. It handles some cell-side logic for equations, such
+ * as how equations are broken up within the text.
+ * 
+ * The current implementation parses innerHTML to create spans based on the text in the cell. 
+ * A more robust/safer approach would directly add elements in the react structure, but this
+ * has been challenging to implement.  
+ */
+
 export interface SchemaCellFieldProps {
     contents: any;
     fieldContents?: FieldViewProps;
@@ -147,20 +157,30 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         return chunkedText;
     }
 
+    /**
+     * Sets the rendered content of the cell to save user inputs. 
+     * @param content the content to set
+     * @param restoreCursorPos whether the cursor should be set back to where it was rather than the 0th index; should usually be true
+     */
     @action 
     setContent = (content: string, restoreCursorPos?: boolean) => {
         const pos = this.cursorPosition;
         this._displayedContent = this.makeSpans(content);
-        console.log('print', content);
         restoreCursorPos && setTimeout(() => this.setCursorPosition(pos));
     }
 
+    //Called from schemaview when a cell is selected to add a reference to the equation
+    /**
+     * Inserts text at the given index.
+     * @param text The text to append.
+     * @param atPos he index at which to insert the text. If empty, defaults to end.
+     */
     @action
-    appendText = (text: string, atCursorPos?: boolean) => {
+    insertText = (text: string, atPos?: boolean) => {
         const content = this._unrenderedContent;
         const cursorPos = this.cursorPosition;
         const robustPos = cursorPos ?? content.length;
-        const newText = atCursorPos ? content.slice(0, robustPos) + text + content.slice(cursorPos ?? content.length) : this._unrenderedContent.concat(text);
+        const newText = atPos ? content.slice(0, robustPos) + text + content.slice(cursorPos ?? content.length) : this._unrenderedContent.concat(text);
         this.onChange(undefined, newText);
         setTimeout(() => this.setCursorPosition(robustPos + text.length));
     }
@@ -172,6 +192,9 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         return wasFocused !== this._editing;
     };
 
+    /**
+     * Gets the cursor's position index within the text being edited.
+     */
     get cursorPosition() {
         const selection = window.getSelection();
         if (!selection || selection.rangeCount === 0 || !this._inputref) return null; 
@@ -185,6 +208,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         return adjRange.toString().length; 
     }
 
+
     setCursorPosition = (position: number | null) => {
         const selection = window.getSelection();
         if (!selection || position === null || !this._inputref) return; 
@@ -220,9 +244,9 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
 
     //This function checks if a visual update (eg. coloring a cell reference) should be made. It's meant to
     //save on processing upkeep vs. constantly rerendering, but I think the savings are minimal for now
-    // shouldUpdate = (prevVal: string, currVal: string) => {
-    //     if (this._props.getCells(currVal).length !== this._props.getCells(prevVal).length) return true;
-    // };
+    shouldUpdate = (prevVal: string, currVal: string) => {
+        if (this._props.getCells(currVal).length !== this._props.getCells(prevVal).length) return true;
+    };
 
     onChange = (e: FormEvent<HTMLDivElement> | undefined, newText?: string) => {
         const prevVal = this._unrenderedContent;
@@ -235,7 +259,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         }
         this._unrenderedContent = targVal;
         this._props.highlightCells?.(targVal);
-        this.setContent(targVal, true);
+        if (this.shouldUpdate(prevVal, targVal)) this.setContent(targVal, true);
         this.setupRefSelect(this.refSelectConditionMet);
     };
 
@@ -248,10 +272,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
     @action
     onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
         if (e.nativeEvent.defaultPrevented) return; // hack .. DashFieldView grabs native events, but react ignores stoppedPropagation and preventDefault, so we need to check it here
-        // if (e.metaKey) {
-        //     e.stopPropagation();
-        //     e.preventDefault();
-        // }
+
         switch (e.key) {
             case 'Tab':
                 e.stopPropagation();
@@ -295,7 +316,6 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         }
     };
 
-
     @action
     onClick = (e?: React.MouseEvent) => {
         if (this._props.editing !== false) {
@@ -312,6 +332,8 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             this._dependencyMessageShown = true;
             return;
         }
+
+        this.setContent(this._unrenderedContent);
         
         if (this._props.SetValue(this._unrenderedContent, shiftDown, enterKey)) {
             this._editing = false;
@@ -327,8 +349,6 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
         }
     }
 
-    //<FieldView {...this._props.fieldContents}/>
-
     staticDisplay = () => {
         return <span className='editableView-static'>
         {
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 6da236d82..3495c5ab4 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -5,23 +5,19 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero, setupMoveUpEvents } from '../../../../ClientUtils';
 import { emptyFunction } from '../../../../Utils';
-import { Colors } from '../../global/globalEnums';
 import './CollectionSchemaView.scss';
 import { EditableView } from '../../EditableView';
 import { ObservableReactComponent } from '../../ObservableReactComponent';
 import { DefaultStyleProvider, returnEmptyDocViewList } from '../../StyleProvider';
 import { FieldViewProps } from '../../nodes/FieldView';
-import { Doc, Field } from '../../../../fields/Doc';
+import { Doc } from '../../../../fields/Doc';
 import { dropActionType } from '../../../util/DropActionTypes';
 import { Transform } from '../../../util/Transform';
 import { SchemaTableCell } from './SchemaTableCell';
 import { DocCast } from '../../../../fields/Types';
 import { computedFn } from 'mobx-utils';
 import { CollectionSchemaView } from './CollectionSchemaView';
-import { SnappingManager } from '../../../util/SnappingManager';
 import { undoable } from '../../../util/UndoManager';
-import { FInfo } from '../../../documents/Documents';
-import { ColumnType } from '../../../../fields/SchemaHeaderField';
 import { IconButton, Size } from 'browndash-components';
 
 export enum SchemaFieldType {
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index ec94a8077..b928a5c67 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -25,6 +25,12 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { infoState } from '../collectionFreeForm/CollectionFreeFormInfoState';
 import { TbShieldX } from 'react-icons/tb';
 
+/**
+ * The SchemaRowBox renders a doc as a row of cells, with each cell representing
+ * one field value of the doc. It mostly handles communication from the SchemaView 
+ * to each SchemaCell, passing down necessary functions are props.
+ */
+
 interface SchemaRowBoxProps extends FieldViewProps {
     rowIndex: number;
 }
@@ -51,10 +57,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         return this.schemaView.Document;
     }
 
-    @computed get rowIndex() {
-        return this.schemaView?.rowIndex(this.Document) ?? -1;
-    }
-
     componentDidMount(): void {
         this._props.setContentViewBox?.(this);
     }
@@ -164,7 +166,6 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                             selectReference={this.selectReference}
                             refSelectModeInfo={this.schemaView._referenceSelectMode}
                             eqHighlightFunc={this.eqHighlightFunc}
-                            equationHighlightRef={this.schemaView._cellHighlightColors}
                             highlightCells={this.highlightCells}
                             isolatedSelection={this.isolatedSelection}
                             key={key}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index e2a05da7f..1bca3c84d 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -30,12 +30,17 @@ import { Colors } from '../../global/globalEnums';
 import { DocumentView } from '../../nodes/DocumentView';
 import { FieldViewProps } from '../../nodes/FieldView';
 import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
-import { CollectionSchemaView, FInfotoColType } from './CollectionSchemaView';
+import { FInfotoColType } from './CollectionSchemaView';
 import './CollectionSchemaView.scss';
 import { SchemaColumnHeader } from './SchemaColumnHeader';
-import { ContextMenu } from '../../ContextMenu';
 import { SchemaCellField } from './SchemaCellField';
 
+/**
+ * SchemaTableCells make up the majority of the visual representation of the SchemaView.
+ * They are rendered for each cell in the SchemaView, and each represents one field value
+ * of a doc. Editing the content of the cell changes the corresponding doc's field value. 
+ */
+
 export interface SchemaTableCellProps {
     Document: Doc;
     col: number;
@@ -62,7 +67,6 @@ export interface SchemaTableCellProps {
     rowSelected: () => boolean;
     isolatedSelection: (doc: Doc) => [boolean, boolean];
     highlightCells: (text: string) => void;
-    equationHighlightRef: ObservableMap<HTMLDivElement, string>;
     eqHighlightFunc: (text: string) => HTMLDivElement[] | [];
     refSelectModeInfo: {enabled: boolean, currEditing: SchemaCellField | undefined};
     selectReference: (doc: Doc, col: number) => void;
@@ -143,11 +147,6 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         return { color, textDecoration, fieldProps, cursor, pointerEvents };
     }
 
-    // @action
-    // appendTextToField = (text: string) => {
-    //     this._fieldRef?.appendText(text);
-    // }
-        
     adjustSelfReference = (field: string) => {
         const modField = field.replace(/\bthis.\b/g, `d${this.docIndex}.`);
         return modField;
-- 
cgit v1.2.3-70-g09d2


From cf45abf8ada938caddb226c825166d4acdee3086 Mon Sep 17 00:00:00 2001
From: Nathan-SR <144961007+Nathan-SR@users.noreply.github.com>
Date: Sun, 29 Sep 2024 19:55:40 -0400
Subject: linting

---
 .../collectionSchema/CollectionSchemaView.tsx      | 56 +++++++++-------------
 .../collectionSchema/SchemaCellField.tsx           |  4 +-
 .../collectionSchema/SchemaColumnHeader.tsx        |  6 +--
 .../collections/collectionSchema/SchemaRowBox.tsx  | 29 +++++------
 .../collectionSchema/SchemaTableCell.tsx           |  8 +---
 .../views/nodes/DataVizBox/DocCreatorMenu.tsx      |  4 ++
 6 files changed, 44 insertions(+), 63 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 11a4e88f9..51b3e1532 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -7,16 +7,15 @@ import * as React from 'react';
 import { ClientUtils, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../ClientUtils';
 import { emptyFunction } from '../../../../Utils';
 import { Doc, DocListCast, Field, FieldType, IdToDoc, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
-import { AclPrivate, DocData } from '../../../../fields/DocSymbols';
+import { DocData } from '../../../../fields/DocSymbols';
 import { Id } from '../../../../fields/FieldSymbols';
 import { List } from '../../../../fields/List';
 import { ColumnType } from '../../../../fields/SchemaHeaderField';
-import { BoolCast, Cast, NumCast, StrCast } from '../../../../fields/Types';
+import { BoolCast, NumCast, StrCast } from '../../../../fields/Types';
 import { DocUtils } from '../../../documents/DocUtils';
 import { Docs, DocumentOptions, FInfo } from '../../../documents/Documents';
 import { DragManager } from '../../../util/DragManager';
 import { dropActionType } from '../../../util/DropActionTypes';
-import { SettingsManager } from '../../../util/SettingsManager';
 import { undoBatch, undoable } from '../../../util/UndoManager';
 import { ContextMenu } from '../../ContextMenu';
 import { EditableView } from '../../EditableView';
@@ -31,20 +30,9 @@ import { CollectionSubView } from '../CollectionSubView';
 import './CollectionSchemaView.scss';
 import { SchemaColumnHeader } from './SchemaColumnHeader';
 import { SchemaRowBox } from './SchemaRowBox';
-import { ActionButton } from '@adobe/react-spectrum';
-import { CollectionMasonryViewFieldRow } from '../CollectionMasonryViewFieldRow';
-import { Func } from 'mocha';
-import { CollectionView } from '../CollectionView';
-import { listSpec } from '../../../../fields/Schema';
-import { GetEffectiveAcl } from '../../../../fields/util';
 import { ContextMenuProps } from '../../ContextMenuItem';
-import { truncate } from 'lodash';
 import { DocumentManager } from '../../../util/DocumentManager';
-import { TbHemispherePlus } from 'react-icons/tb';
-import { docs_v1 } from 'googleapis';
 import { SchemaCellField } from './SchemaCellField';
-import { threadId } from 'worker_threads';
-import { FontIconBox } from '../../nodes/FontIconBox/FontIconBox';
 import { SnappingManager } from '../../../util/SnappingManager';
 
 /**
@@ -458,7 +446,7 @@ export class CollectionSchemaView extends CollectionSubView() {
      * @returns column index
      */
     findColDropIndex = (mouseX: number) => {
-        let xOffset: number = this._props.ScreenToLocalTransform().inverse().transformPoint(0,0)[0] + CollectionSchemaView._rowMenuWidth; 
+        const xOffset: number = this._props.ScreenToLocalTransform().inverse().transformPoint(0,0)[0] + CollectionSchemaView._rowMenuWidth; 
         let index: number | undefined;
         this.displayColumnWidths.reduce((total, curr, i) => {
             if (total <= mouseX && total + curr >= mouseX) {
@@ -562,7 +550,7 @@ export class CollectionSchemaView extends CollectionSubView() {
      */
     highlightSortedColumn = (field?: string, descending?: boolean) => {
         let index = -1;
-        let highlightColors: string[] = [];
+        const highlightColors: string[] = [];
         const rowCount: number = this._containedDocs.length + 1;
         if (field || this.sortField){
             index = this.columnKeys.indexOf(field || this.sortField);
@@ -1169,20 +1157,20 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     /**
-     * Gets docs contained by collections within the schema
+     * Gets docs contained by collections within the schema. Currently defunct.
      * @param doc 
      * @param displayed 
      * @returns 
      */
-    subCollectionDocs = (doc: Doc, displayed: boolean) => {
-        const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]);
-        let collections: Array<Doc> = [];
-        if (displayed) collections = childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema);
-        else collections = childDocs.filter(d => d.type === 'collection' && !d._childrenSharedWithSchema);
-        let toReturn: Doc[] = [...childDocs];
-        collections.forEach(d => toReturn = toReturn.concat(this.subCollectionDocs(d, displayed)));
-        return toReturn;
-    }
+    // subCollectionDocs = (doc: Doc, displayed: boolean) => {
+    //     const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]);
+    //     let collections: Array<Doc> = [];
+    //     if (displayed) collections = childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema);
+    //     else collections = childDocs.filter(d => d.type === 'collection' && !d._childrenSharedWithSchema);
+    //     let toReturn: Doc[] = [...childDocs];
+    //     collections.forEach(d => toReturn = toReturn.concat(this.subCollectionDocs(d, displayed)));
+    //     return toReturn;
+    // }
 
     /**
      * Applies any filters active on the schema to filter out docs that don't match.
@@ -1234,16 +1222,16 @@ export class CollectionSchemaView extends CollectionSubView() {
      * Returns all child docs of the schema and child docs of contained collections that satisfy applied filters.
      */
     @computed get docs() {
-        let docsFromChildren: Doc[] = [];
+        //let docsFromChildren: Doc[] = [];
 
-        const displayedCollections = this.childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema);
-        displayedCollections.forEach(d => {
-            let docsNotAlreadyDisplayed = this.subCollectionDocs(d, true).filter(dc => !this._containedDocs.includes(dc));
-            docsFromChildren = docsFromChildren.concat(docsNotAlreadyDisplayed);
-        });
-        let docs = this.filteredDocs;
+        // Functionality for adding child docs
+        //const displayedCollections = this.childDocs.filter(d => d.type === 'collection' && d._childrenSharedWithSchema);
+        // displayedCollections.forEach(d => {
+        //     let docsNotAlreadyDisplayed = this.subCollectionDocs(d, true).filter(dc => !this._containedDocs.includes(dc));
+        //     docsFromChildren = docsFromChildren.concat(docsNotAlreadyDisplayed);
+        // });
 
-        return docs;
+        return this.filteredDocs;;
     }
 
     /**
diff --git a/src/client/views/collections/collectionSchema/SchemaCellField.tsx b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
index 72dcc00e6..065544ac9 100644
--- a/src/client/views/collections/collectionSchema/SchemaCellField.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaCellField.tsx
@@ -148,10 +148,8 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             }
         }
 
-        let matchNum = 0;
         matches.forEach((match: string) => {
             chunkedText = chunkedText.replace(match, this.generateSpan(match, cells.get(match)));
-            ++matchNum;
         })
 
         return chunkedText;
@@ -365,7 +363,7 @@ export class SchemaCellField extends ObservableReactComponent<SchemaCellFieldPro
             className='schemaField-editing'
             ref={r => { this._inputref = r; }}
             style={{ cursor: 'text', outline: 'none', overflow: 'auto', minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20, }}
-            onBlur={e => {this._props.refSelectModeInfo.enabled ? setTimeout(() => {this.setIsFocused(true)}, 1000) : this.finalizeEdit(false, true, false)}}
+            onBlur={() => {this._props.refSelectModeInfo.enabled ? setTimeout(() => {this.setIsFocused(true)}, 1000) : this.finalizeEdit(false, true, false)}}
             autoFocus
             onInput={this.onChange}
             onKeyDown={this.onKeyDown}
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index 3495c5ab4..cf4fe4ef4 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -147,7 +147,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
                         this._altTitle = undefined;
                         this._props.finishEdit?.();
                         return true;
-                    } else if (enterKey) this.updateAlt(value);
+                    }
                     this._props.finishEdit?.(); 
                     return true;
                 }, 'edit column header')}
@@ -157,7 +157,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
 
     public static isDefaultField = (key: string) => {
         const defaultPattern = /EmptyColumnKey/;
-        let isDefault: boolean = (defaultPattern.exec(key) != null);
+        const isDefault: boolean = (defaultPattern.exec(key) != null);
         return isDefault;
     }
 
@@ -220,7 +220,7 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
                         setupMoveUpEvents(
                             this,
                             e,
-                            e => {return this._inputRef?.setIsEditing(false) ?? false},
+                            () => {return this._inputRef?.setIsEditing(false) ?? false},
                             emptyFunction,
                             emptyFunction,
                             );
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index b928a5c67..a8a4ef2c2 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -3,27 +3,21 @@ import { computed, makeObservable, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import { computedFn } from 'mobx-utils';
 import * as React from 'react';
-import { CgClose, CgLock, CgLockUnlock, CgMenu } from 'react-icons/cg';
-import { FaExternalLinkAlt } from 'react-icons/fa';
 import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils';
 import { emptyFunction } from '../../../../Utils';
-import { Doc, DocListCast, FieldResult } from '../../../../fields/Doc';
+import { Doc } from '../../../../fields/Doc';
 import { BoolCast } from '../../../../fields/Types';
 import { Transform } from '../../../util/Transform';
 import { undoable } from '../../../util/UndoManager';
 import { ViewBoxBaseComponent } from '../../DocComponent';
-import { Colors } from '../../global/globalEnums';
 import { FieldView, FieldViewProps } from '../../nodes/FieldView';
 import { OpenWhere } from '../../nodes/OpenWhere';
 import { CollectionSchemaView } from './CollectionSchemaView';
 import './CollectionSchemaView.scss';
 import { SchemaTableCell } from './SchemaTableCell';
 import { ContextMenu } from '../../ContextMenu';
-import { CollectionFreeFormView } from '../collectionFreeForm';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
-import { infoState } from '../collectionFreeForm/CollectionFreeFormInfoState';
-import { TbShieldX } from 'react-icons/tb';
 
 /**
  * The SchemaRowBox renders a doc as a row of cells, with each cell representing
@@ -78,16 +72,17 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
             event: () => this.schemaView.removeDoc(this.Document),
             icon: 'minus',
         });
-        const childDocs = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)])
-        if (this.Document.type === 'collection' && childDocs.length) {
-                ContextMenu.Instance.addItem({
-                description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema',
-                event: () => {
-                    this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; 
-                },
-                icon: this.Document._childrenSharedWithSchema ? 'minus' : 'plus',
-            });
-        }
+        // Defunct option to add child docs of collections to the main schema
+        // const childDocs = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)])
+        // if (this.Document.type === 'collection' && childDocs.length) {
+        //         ContextMenu.Instance.addItem({
+        //         description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema',
+        //         event: () => {
+        //             this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; 
+        //         },
+        //         icon: this.Document._childrenSharedWithSchema ? 'minus' : 'plus',
+        //     });
+        // }
         ContextMenu.Instance.displayMenu(x, y, undefined, false);
     }
 
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index 1bca3c84d..247739fd2 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -3,7 +3,7 @@
 /* eslint-disable no-use-before-define */
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Popup, Size, Type } from 'browndash-components';
-import { ObservableMap, action, computed, makeObservable, observable } from 'mobx';
+import { action, computed, makeObservable, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import { extname } from 'path';
 import * as React from 'react';
@@ -161,14 +161,10 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
 
         const idPattern = /idToDoc\((.*?)\)/g;
         let matches;
-        let results = new Array<[id: string, func: string]>();
+        const results = new Array<[id: string, func: string]>();
         while ((matches = idPattern.exec(field)) !== null) {results.push([matches[0], matches[1].replace(/"/g, '')]); }
         results.forEach((idFuncPair) => {modField = modField.replace(idFuncPair[0], 'd' + (DocumentView.getDocViewIndex(IdToDoc(idFuncPair[1]))).toString());})
 
-        for (let i = 0; i < modField.length; ++i){
-            
-        }
-
         if (modField.endsWith(';')) modField = modField.substring(0, modField.length - 1);
 
         const inQuotes = (field: string) => {return ((field.startsWith('`') && field.endsWith('`')) || (field.startsWith("'") && field.endsWith("'")) || (field.startsWith('"') && field.endsWith('"')))}
diff --git a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
index bb9ea7e17..5d5c35dce 100644
--- a/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
+++ b/src/client/views/nodes/DataVizBox/DocCreatorMenu.tsx
@@ -2181,4 +2181,8 @@ export class TemplateLayouts {
 //         }]
 //     };
 
+}
+
+export class ContentField extends Field {
+    
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 9323ad30103b474e95610e97eb92916a0cf71f7b Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 4 Oct 2024 21:35:22 -0400
Subject: more lint fixes to schema view changes.

---
 src/ClientUtils.ts                                 |   5 +-
 src/client/util/LinkManager.ts                     |   2 +-
 src/client/util/Scripting.ts                       |   8 +-
 src/client/util/SelectionManager.ts                |   1 -
 src/client/views/FieldsDropdown.tsx                |   4 +-
 src/client/views/PropertiesView.tsx                |   2 +-
 .../collectionSchema/CollectionSchemaView.tsx      | 327 +++++++++++----------
 .../collectionSchema/SchemaColumnHeader.tsx        | 264 +++++++++--------
 .../collections/collectionSchema/SchemaRowBox.tsx  |  48 +--
 .../collectionSchema/SchemaTableCell.tsx           |  82 +++---
 src/client/views/global/globalScripts.ts           |   1 -
 src/client/views/nodes/DataVizBox/DataVizBox.tsx   | 177 ++++++-----
 src/client/views/nodes/DocumentIcon.tsx            |  10 +-
 src/client/views/nodes/FieldView.tsx               |   2 +-
 src/client/views/nodes/LabelBox.tsx                |   4 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |   2 -
 16 files changed, 485 insertions(+), 454 deletions(-)

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

diff --git a/src/ClientUtils.ts b/src/ClientUtils.ts
index 8ecbc55bf..3066499d8 100644
--- a/src/ClientUtils.ts
+++ b/src/ClientUtils.ts
@@ -317,7 +317,7 @@ export namespace ClientUtils {
     }
 
     export function lightenRGB(rVal: number, gVal: number, bVal: number, percent: number): [number, number, number] {
-        const amount = 1 + percent/100;
+        const amount = 1 + percent / 100;
         const r = rVal * amount;
         const g = gVal * amount;
         const b = bVal * amount;
@@ -347,8 +347,6 @@ export namespace ClientUtils {
         return undefined;
     }
 
-    
-
     export function GetClipboardText(): string {
         const textArea = document.createElement('textarea');
         document.body.appendChild(textArea);
@@ -725,7 +723,6 @@ export function UpdateIcon(
     const newDiv = docViewContent.cloneNode(true) as HTMLDivElement;
     newDiv.style.width = width.toString();
     newDiv.style.height = height.toString();
-    console.log('width: ' + newDiv.style.width)
     replaceCanvases(docViewContent, newDiv);
     const htmlString = new XMLSerializer().serializeToString(newDiv);
     const nativeWidth = width;
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index bbf8d9c11..e11482572 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -260,7 +260,7 @@ export function UPDATE_SERVER_CACHE() {
     Doc.MyDockedBtns.linearView_IsOpen && console.log('Set cached docs = ');
     const isFiltered = filtered.filter(doc => !Doc.IsSystem(doc));
     const strings = isFiltered.map(doc => StrCast(doc.title) + ' ' + (Doc.IsDataProto(doc) ? '(data)' : '(embedding)'));
-    //Doc.MyDockedBtns.linearView_IsOpen && strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str));
+    Doc.MyDockedBtns.linearView_IsOpen && strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str));
 
     rp.post(ClientUtils.prepend('/setCacheDocumentIds'), {
         body: {
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index 3ba3ff4b5..b1db0bf39 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -81,6 +81,7 @@ function Run(script: string | undefined, customParams: string[], diagnostics: ts
             if (!options.editable) {
                 batch = Doc.MakeReadOnly();
             }
+
             const result = compiledFunction.apply(thisParam, params).apply(thisParam, argsArray);
             batch?.end();
             return { success: true, result };
@@ -177,13 +178,8 @@ function forEachNode(node: ts.Node, onEnter: Traverser, onExit?: Traverser, inde
     );
 }
 
-// ScriptField.CompileScript(value, {}, true, undefined, DocumentIconContainer.getTransformer());
-// //addreturn = true
-// //capturedvariables = undefined
-// //
-
 export function CompileScript(script: string, options: ScriptOptions = {}): CompileResult {
-    const captured = options.capturedVariables ?? {}; 
+    const captured = options.capturedVariables ?? {};
     const signature = Object.keys(captured).reduce((p, v) => {
         const formatCapture = (obj: FieldType | undefined) => `${v}=${obj instanceof RefField ? 'XXX' : obj?.toString()}`;
         const captureVal = captured[v];
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index c39d8ebc7..1ab84421c 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -58,7 +58,6 @@ export class SelectionManager {
     });
 
     public static DeselectAll = (except?: Doc): void => {
-        
         const found = this.Instance.SelectedViews.find(dv => dv.Document === except);
         runInAction(() => {
             if (LinkManager.Instance) {
diff --git a/src/client/views/FieldsDropdown.tsx b/src/client/views/FieldsDropdown.tsx
index 176ac96b6..407031b40 100644
--- a/src/client/views/FieldsDropdown.tsx
+++ b/src/client/views/FieldsDropdown.tsx
@@ -34,7 +34,7 @@ export class FieldsDropdown extends ObservableReactComponent<fieldsDropdownProps
         makeObservable(this);
     }
 
-    @computed get allDescendantDocs() { //!!!
+    @computed get allDescendantDocs() {
         const allDocs = new Set<Doc>();
         SearchUtil.foreachRecursiveDoc([this._props.Document], (depth, doc) => allDocs.add(doc));
         return Array.from(allDocs);
@@ -57,7 +57,7 @@ export class FieldsDropdown extends ObservableReactComponent<fieldsDropdownProps
         const filteredOptions = ['author', ...(this._newField ? [this._newField] : []), ...(this._props.addedFields ?? []), ...this.fieldsOfDocuments.filter(facet => facet[0] === facet.charAt(0).toUpperCase())];
 
         Object.entries(DocOptions)
-            .filter(opts => opts[1].filterable) //!!!
+            .filter(opts => opts[1].filterable)
             .forEach((pair: [string, FInfo]) => filteredOptions.push(pair[0]));
         const options = filteredOptions.sort().map(facet => ({ value: facet, label: facet }));
 
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 69c46052e..c6dccb4fb 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -884,7 +884,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
     @computed get borderColor() {
         const doc = this.selectedDoc;
         const layoutDoc = doc ? Doc.Layout(doc) : doc;
-        return StrCast(layoutDoc);
+        return StrCast(layoutDoc.color);
     }
     set borderColor(value) { this.selectedDoc && (this.selectedDoc[DocData].color = value || undefined); } // prettier-ignore
 
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 0076caaf8..aef97e723 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1,12 +1,11 @@
-/* eslint-disable no-restricted-syntax */
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { IconButton, Popup, PopupTrigger, Size, Type } from 'browndash-components';
-import { IReactionDisposer, ObservableMap, action, autorun, computed, makeObservable, observable, observe, override, reaction, runInAction } from 'mobx';
+import { IconButton, Size } from 'browndash-components';
+import { IReactionDisposer, Lambda, ObservableMap, action, computed, makeObservable, observable, observe, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { ClientUtils, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../ClientUtils';
 import { emptyFunction } from '../../../../Utils';
-import { Doc, DocListCast, Field, FieldType, IdToDoc, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
+import { Doc, DocListCast, Field, FieldType, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
 import { DocData } from '../../../../fields/DocSymbols';
 import { Id } from '../../../../fields/FieldSymbols';
 import { List } from '../../../../fields/List';
@@ -14,10 +13,13 @@ import { ColumnType } from '../../../../fields/SchemaHeaderField';
 import { BoolCast, NumCast, StrCast } from '../../../../fields/Types';
 import { DocUtils } from '../../../documents/DocUtils';
 import { Docs, DocumentOptions, FInfo } from '../../../documents/Documents';
+import { DocumentManager } from '../../../util/DocumentManager';
 import { DragManager } from '../../../util/DragManager';
 import { dropActionType } from '../../../util/DropActionTypes';
+import { SnappingManager } from '../../../util/SnappingManager';
 import { undoBatch, undoable } from '../../../util/UndoManager';
 import { ContextMenu } from '../../ContextMenu';
+import { ContextMenuProps } from '../../ContextMenuItem';
 import { EditableView } from '../../EditableView';
 import { ObservableReactComponent } from '../../ObservableReactComponent';
 import { StyleProp } from '../../StyleProp';
@@ -28,25 +30,23 @@ import { FieldViewProps } from '../../nodes/FieldView';
 import { FocusViewOptions } from '../../nodes/FocusViewOptions';
 import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView';
 import './CollectionSchemaView.scss';
+import { SchemaCellField } from './SchemaCellField';
 import { SchemaColumnHeader } from './SchemaColumnHeader';
 import { SchemaRowBox } from './SchemaRowBox';
-import { ContextMenuProps } from '../../ContextMenuItem';
-import { DocumentManager } from '../../../util/DocumentManager';
-import { SchemaCellField } from './SchemaCellField';
-import { SnappingManager } from '../../../util/SnappingManager';
 
 /**
  * The schema view offers a spreadsheet-like interface for users to interact with documents. Within the schema,
- * each doc is represented by its own row. Each column represents a field, for example the author or title fields. 
+ * each doc is represented by its own row. Each column represents a field, for example the author or title fields.
  * Users can apply varoius filters and sorts to columns to change what is displayed. The schemaview supports equations for
  * cell linking.
- * 
+ *
  * This class supports the main functionality for choosing which docs to render in the view, applying visual
- * updates to rows and columns (such as user dragging or sort-related highlighting), applying edits to multiple cells 
+ * updates to rows and columns (such as user dragging or sort-related highlighting), applying edits to multiple cells
  * at once, and applying filters and sorts to columns. It contains SchemaRowBoxes (which themselves contain SchemaTableCells,
  * and SchemaCellFields) and SchemaColumnHeaders.
  */
 
+// eslint-disable-next-line @typescript-eslint/no-require-imports
 const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore
 
 export const FInfotoColType: { [key: string]: ColumnType } = {
@@ -63,7 +63,7 @@ const defaultColumnKeys: string[] = ['title', 'type', 'author', 'author_date', '
 
 @observer
 export class CollectionSchemaView extends CollectionSubView() {
-    private _keysDisposer: any;
+    private _keysDisposer?: Lambda;
     private _disposers: { [name: string]: IReactionDisposer } = {};
     private _previewRef: HTMLDivElement | null = null;
     private _makeNewColumn: boolean = false;
@@ -71,13 +71,14 @@ export class CollectionSchemaView extends CollectionSubView() {
     private _tableContentRef: HTMLDivElement | null = null;
     private _menuTarget = React.createRef<HTMLDivElement>();
     private _headerRefs: SchemaColumnHeader[] = [];
-    private _eqHighlightColors: Array<[{r: number, g: number, b: number}, {r: number, g: number, b: number}]> = [];
+    private _eqHighlightColors: Array<[{ r: number; g: number; b: number }, { r: number; g: number; b: number }]> = [];
+    private _oldWheel: HTMLDivElement | null = null;
 
     constructor(props: SubCollectionViewProps) {
         super(props);
         makeObservable(this);
         const lightenedColor = (r: number, g: number, b:number) => { const lightened = ClientUtils.lightenRGB(r, g, b, 165); return {r: lightened[0], g: lightened[1], b: lightened[2]}} // prettier-ignore
-        const colors = (r: number, g: number, b: number): [any, any] => {return [{r: r, g: g, b: b}, lightenedColor(r, g, b)]} // prettier-ignore
+        const colors = (r: number, g: number, b: number):[{r:number,g:number,b:number},{r:number,g:number,b:number}] => ([{r, g, b}, lightenedColor(r, g, b)]); // prettier-ignore
         this._eqHighlightColors.push(colors(70, 150, 50));
         this._eqHighlightColors.push(colors(180, 70, 20));
         this._eqHighlightColors.push(colors(70, 50, 150));
@@ -122,8 +123,8 @@ export class CollectionSchemaView extends CollectionSubView() {
     @observable _highlightedCellsInfo: Array<[doc: Doc, field: string]> = [];
     @observable _cellHighlightColors: ObservableMap = new ObservableMap<string, string[]>();
     @observable _containedDocs: Doc[] = []; //all direct children of the schema
-    @observable _referenceSelectMode: {enabled: boolean, currEditing: SchemaCellField | undefined} = {enabled: false, currEditing: undefined}
-    
+    @observable _referenceSelectMode: { enabled: boolean; currEditing: SchemaCellField | undefined } = { enabled: false, currEditing: undefined };
+
     // target HTMLelement portal for showing a popup menu to edit cell values.
     public get MenuTarget() {
         return this._menuTarget.current;
@@ -217,15 +218,17 @@ export class CollectionSchemaView extends CollectionSubView() {
             true
         );
         this._disposers.docdata = reaction(
-            () => DocListCast(this.dataDoc[this.fieldKey]), 
-            (docs) => this._containedDocs = docs,
-            {fireImmediately: true}
-        )
+            () => DocListCast(this.dataDoc[this.fieldKey]),
+            docs => (this._containedDocs = docs),
+            { fireImmediately: true }
+        );
         this._disposers.sortHighlight = reaction(
-            () => [this.sortField, this._containedDocs, this._selectedDocs, this._highlightedCellsInfo], 
-            () => {this.sortField && setTimeout(() => this.highlightSortedColumn())},
-            {fireImmediately: true}
-        )
+            () => [this.sortField, this._containedDocs, this._selectedDocs, this._highlightedCellsInfo],
+            () => {
+                this.sortField && setTimeout(() => this.highlightSortedColumn());
+            },
+            { fireImmediately: true }
+        );
     }
 
     componentWillUnmount() {
@@ -239,8 +242,8 @@ export class CollectionSchemaView extends CollectionSubView() {
 
     removeDoc = (doc: Doc) => {
         this.removeDocument(doc);
-        this._containedDocs = this._containedDocs.filter(d => d !== doc)
-    }
+        this._containedDocs = this._containedDocs.filter(d => d !== doc);
+    };
 
     rowIndex = (doc: Doc) => this.docsWithDrag.docs.indexOf(doc);
 
@@ -301,7 +304,9 @@ export class CollectionSchemaView extends CollectionSubView() {
                     }
                     break;
                 case 'Backspace': {
-                    undoable(() => {this._selectedDocs.forEach(d => this._containedDocs.includes(d) && this.removeDoc(d));}, 'delete schema row');
+                    undoable(() => {
+                        this._selectedDocs.forEach(d => this._containedDocs.includes(d) && this.removeDoc(d));
+                    }, 'delete schema row');
                     break;
                 }
                 case 'Escape': {
@@ -319,7 +324,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     addRow = (doc: Doc | Doc[]) => this.addDocument(doc);
 
     @undoBatch
-    changeColumnKey = (index: number, newKey: string, defaultVal?: any) => {
+    changeColumnKey = (index: number, newKey: string, defaultVal?: FieldType) => {
         if (!this.documentKeys.includes(newKey)) this.addNewKey(newKey, defaultVal);
 
         const currKeys = this.columnKeys.slice(); // copy the column key array first, then change it.
@@ -328,9 +333,10 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     @undoBatch
-    addColumn = (index: number = 0, key?: string, defaultVal?: any) => {
+    addColumn = (index: number = 0, keyIn?: string, defaultVal?: FieldType) => {
+        let key = keyIn;
         if (key && !this.documentKeys.includes(key)) this.addNewKey(key, defaultVal);
-        
+
         const newColWidth = this.tableWidth / (this.storedColumnWidths.length + 1);
         const currWidths = this.storedColumnWidths.slice();
         currWidths.splice(index, 0, newColWidth);
@@ -345,11 +351,11 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     @action
-    addNewKey = (key: string, defaultVal: any) => {
+    addNewKey = (key: string, defaultVal: FieldType | undefined) => {
         this.childDocs.forEach(doc => {
             doc[DocData][key] = defaultVal;
         });
-    }
+    };
 
     @undoBatch
     removeColumn = (index: number) => {
@@ -365,13 +371,13 @@ export class CollectionSchemaView extends CollectionSubView() {
 
         const currKeys = this.columnKeys.slice();
         currKeys.splice(index, 1);
-        this.layoutDoc.schema_columnKeys = new List<string>(currKeys); 
+        this.layoutDoc.schema_columnKeys = new List<string>(currKeys);
 
         this._colEles.splice(index, 1);
     };
 
     @action
-    startResize = (e: any, index: number, rightSide: boolean) => {
+    startResize = (e: React.PointerEvent, index: number, rightSide: boolean) => {
         this._displayColumnWidths = this.storedColumnWidths;
         setupMoveUpEvents(this, e, moveEv => this.resizeColumn(moveEv, index, rightSide), this.finishResize, emptyFunction);
     };
@@ -384,8 +390,8 @@ export class CollectionSchemaView extends CollectionSubView() {
 
             let change = e.movementX;
 
-            if (rightSide && (index !== this._displayColumnWidths.length - 1)) {
-                growing = change < 0 ? index + 1: index;
+            if (rightSide && index !== this._displayColumnWidths.length - 1) {
+                growing = change < 0 ? index + 1 : index;
                 shrinking = change < 0 ? index : index + 1;
             } else if (index !== 0) {
                 growing = change < 0 ? index : index - 1;
@@ -432,7 +438,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         this.closeNewColumnMenu();
         this._headerRefs.forEach(ref => ref.toggleEditing(false));
         this._draggedColIndex = index;
-        this.setColDrag(true);  
+        this.setColDrag(true);
         const dragData = new DragManager.ColumnDragData(index);
         const dragEles = [this._colEles[index]];
         this.childDocs.forEach(doc => dragEles.push(this._rowEles.get(doc).children[1].children[index]));
@@ -446,7 +452,7 @@ export class CollectionSchemaView extends CollectionSubView() {
      * @returns column index
      */
     findColDropIndex = (mouseX: number) => {
-        const xOffset: number = this._props.ScreenToLocalTransform().inverse().transformPoint(0,0)[0] + CollectionSchemaView._rowMenuWidth; 
+        const xOffset: number = this._props.ScreenToLocalTransform().inverse().transformPoint(0, 0)[0] + CollectionSchemaView._rowMenuWidth;
         let index: number | undefined;
         this.displayColumnWidths.reduce((total, curr, i) => {
             if (total <= mouseX && total + curr >= mouseX) {
@@ -507,12 +513,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         this._colEles.forEach((colRef, i) => {
             const edgeStyle = i === index ? `solid 2px ${Colors.MEDIUM_BLUE}` : '';
             const sorted = i === this.columnKeys.indexOf(this.sortField);
-            const cellEles = [
-                colRef,
-                ...this.docsWithDrag.docs 
-                    .filter(doc => (i !== this._selectedCol || !this._selectedDocs.includes(doc)) && !sorted)
-                    .map(doc => this._rowEles.get(doc).children[1].children[i]),
-            ];
+            const cellEles = [colRef, ...this.docsWithDrag.docs.filter(doc => (i !== this._selectedCol || !this._selectedDocs.includes(doc)) && !sorted).map(doc => this._rowEles.get(doc).children[1].children[i])];
             cellEles.forEach(ele => {
                 if (sorted || this.highlightedCells.includes(ele)) return;
                 ele.style.borderTop = ele === cellEles[0] ? edgeStyle : '';
@@ -533,14 +534,14 @@ export class CollectionSchemaView extends CollectionSubView() {
 
             this.childDocs.forEach(doc => {
                 const cell = this._rowEles.get(doc).children[1].children[i];
-                if (!(this._selectedDocs.includes(doc) && i === this._selectedCol) && !(this.highlightedCells.includes(cell)) && cell) {
+                if (!(this._selectedDocs.includes(doc) && i === this._selectedCol) && !this.highlightedCells.includes(cell) && cell) {
                     cell.style.borderLeft = '';
                     cell.style.borderRight = '';
                     cell.style.borderBottom = '';
                 }
             });
         });
-    }
+    };
 
     /**
      * Applies a gradient highlight to a sorted column. The direction of the gradient depends
@@ -552,10 +553,10 @@ export class CollectionSchemaView extends CollectionSubView() {
         let index = -1;
         const highlightColors: string[] = [];
         const rowCount: number = this._containedDocs.length + 1;
-        if (field || this.sortField){
+        if (field || this.sortField) {
             index = this.columnKeys.indexOf(field || this.sortField);
-            const increment: number = 110/rowCount;
-            for (let i = 1; i <= rowCount; ++i){
+            const increment: number = 110 / rowCount;
+            for (let i = 1; i <= rowCount; ++i) {
                 const adjColor = ClientUtils.lightenRGB(16, 66, 230, increment * i);
                 highlightColors.push(`solid 2px rgb(${adjColor[0]}, ${adjColor[1]}, ${adjColor[2]})`);
             }
@@ -564,25 +565,20 @@ export class CollectionSchemaView extends CollectionSubView() {
         this._colEles.forEach((colRef, i) => {
             const highlight: boolean = i === index;
             const desc: boolean = descending || this.sortDesc;
-            const cellEles = [
-                colRef,
-                ...this.docsWithDrag.docs 
-                    .filter(doc => (i !== this._selectedCol || !this._selectedDocs.includes(doc)))
-                    .map(doc => this._rowEles.get(doc).children[1].children[i]),
-            ];
+            const cellEles = [colRef, ...this.docsWithDrag.docs.filter(doc => i !== this._selectedCol || !this._selectedDocs.includes(doc)).map(doc => this._rowEles.get(doc).children[1].children[i])];
             const cellCount = cellEles.length;
-            for (let ele = 0; ele < cellCount; ++ele){
+            for (let ele = 0; ele < cellCount; ++ele) {
                 const currCell = cellEles[ele];
                 if (this.highlightedCells.includes(currCell)) continue;
-                const style = highlight ? desc ? `${highlightColors[cellCount - 1 - ele]}` : `${highlightColors[ele]}` : '';
+                const style = highlight ? (desc ? `${highlightColors[cellCount - 1 - ele]}` : `${highlightColors[ele]}`) : '';
                 currCell.style.borderLeft = style;
                 currCell.style.borderRight = style;
             }
-            cellEles[0].style.borderTop = highlight ? desc ? `${highlightColors[cellCount - 1]}` : `${highlightColors[0]}` : '';
-            if (!(this._selectedDocs.includes(this.docsWithDrag.docs[this.docsWithDrag.docs.length - 1]) && this._selectedCol === index) && !this.highlightedCells.includes(cellEles[cellCount - 1])) cellEles[cellCount - 1].style.borderBottom = highlight ? desc ? `${highlightColors[0]}` :  `${highlightColors[cellCount - 1]}` : ''; 
+            cellEles[0].style.borderTop = highlight ? (desc ? `${highlightColors[cellCount - 1]}` : `${highlightColors[0]}`) : '';
+            if (!(this._selectedDocs.includes(this.docsWithDrag.docs[this.docsWithDrag.docs.length - 1]) && this._selectedCol === index) && !this.highlightedCells.includes(cellEles[cellCount - 1]))
+                cellEles[cellCount - 1].style.borderBottom = highlight ? (desc ? `${highlightColors[0]}` : `${highlightColors[cellCount - 1]}`) : '';
         });
-        
-    }
+    };
 
     /**
      * Gets the html element representing a cell so that styles can be applied on it.
@@ -594,35 +590,40 @@ export class CollectionSchemaView extends CollectionSubView() {
         const index = this.columnKeys.indexOf(fieldKey);
         const cell = this._rowEles.get(doc).children[1].children[index];
         return cell;
-    }
+    };
 
     /**
      * Given text in a cell, find references to other cells (for equations).
      * @param text the text in the cell
-     * @returns the html cell elements referenced in the text. 
+     * @returns the html cell elements referenced in the text.
      */
     findCellRefs = (text: string) => {
         const pattern = /(this|d(\d+))\.(\w+)/g;
-        interface Match { docRef: string; field: string; }
+        interface Match {
+            docRef: string;
+            field: string;
+        }
 
         const matches: Match[] = [];
         let match: RegExpExecArray | null;
 
         while ((match = pattern.exec(text)) !== null) {
-            const docRef = match[1] === 'this' ? match[1] : match[2]; 
+            const docRef = match[1] === 'this' ? match[1] : match[2];
             matches.push({ docRef, field: match[3] });
         }
 
-        const cells: Array<any> = [];
-        matches.forEach((match: Match) => {
-            const {docRef, field} = match;
+        const cells: [Doc, string][] = [];
+        matches.forEach((m: Match) => {
+            const { docRef, field } = m;
             const docView = DocumentManager.Instance.DocumentViews[Number(docRef)];
             const doc = docView?.Document ?? undefined;
-            if (this.columnKeys.includes(field) && this._containedDocs.includes(doc)) {cells.push([doc, field])}
-        })
+            if (this.columnKeys.includes(field) && this._containedDocs.includes(doc)) {
+                cells.push([doc, field]);
+            }
+        });
 
         return cells;
-    }
+    };
 
     /**
      * Determines whether the rows above or below a given row have been
@@ -636,7 +637,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         const selectedBelow: boolean = this._selectedDocs.includes(docs[index + 1]);
         const selectedAbove: boolean = this._selectedDocs.includes(docs[index - 1]);
         return [selectedAbove, selectedBelow];
-    }
+    };
 
     @action
     removeCellHighlights = () => {
@@ -649,9 +650,10 @@ export class CollectionSchemaView extends CollectionSubView() {
                 if (this.selectionOverlap(doc)[0]) cell.style.borderTop = '';
                 if (this.selectionOverlap(doc)[1]) cell.style.borderBottom = '';
             } else cell.style.border = '';
-            cell.style.backgroundColor = '';});
+            cell.style.backgroundColor = '';
+        });
         this._highlightedCellsInfo = [];
-    }
+    };
 
     restoreCellHighlights = () => {
         this._highlightedCellsInfo.forEach(info => {
@@ -665,10 +667,10 @@ export class CollectionSchemaView extends CollectionSubView() {
             cell.style.borderRight = color;
             cell.style.borderBottom = color;
         });
-    }
+    };
 
     /**
-     * Highlights cells based on equation text in the cell currently being edited. 
+     * Highlights cells based on equation text in the cell currently being edited.
      * Does not highlight selected cells (that's done directly in SchemaTableCell).
      * @param text the equation
      */
@@ -682,7 +684,7 @@ export class CollectionSchemaView extends CollectionSubView() {
             const info = this._highlightedCellsInfo[i];
             const color = this._eqHighlightColors[i % 10];
             const colorStrings = [`solid 2px rgb(${color[0].r}, ${color[0].g}, ${color[0].b})`, `rgb(${color[1].r}, ${color[1].g}, ${color[1].b})`];
-            const doc = info[0]; 
+            const doc = info[0];
             const field = info[1];
             const key = `${doc[Id]}_${field}`;
             const cell = this.getCellElement(doc, field);
@@ -690,7 +692,7 @@ export class CollectionSchemaView extends CollectionSubView() {
             cell.style.border = colorStrings[0];
             cell.style.backgroundColor = colorStrings[1];
         }
-    }
+    };
 
     //Used in SchemaRowBox
     @action
@@ -718,7 +720,6 @@ export class CollectionSchemaView extends CollectionSubView() {
         this.deselectAllCells();
     };
 
-
     selectRow = (doc: Doc, lastSelected: Doc) => {
         const index = this.rowIndex(doc);
         const lastSelectedRow = this.rowIndex(lastSelected);
@@ -737,12 +738,12 @@ export class CollectionSchemaView extends CollectionSubView() {
         if (!doc) return;
         const docIndex = DocumentView.getDocViewIndex(doc);
         const field = this.columnKeys[col];
-        const refToAdd = `d${docIndex}.${field}`
-        const editedField = this._referenceSelectMode.currEditing ? this._referenceSelectMode.currEditing as SchemaCellField : null;
+        const refToAdd = `d${docIndex}.${field}`;
+        const editedField = this._referenceSelectMode.currEditing ? (this._referenceSelectMode.currEditing as SchemaCellField) : null;
         editedField?.insertText(refToAdd, true);
         editedField?.setupRefSelect(false);
         return;
-    }
+    };
 
     @action
     selectCell = (doc: Doc, col: number, shiftKey: boolean, ctrlKey: boolean) => {
@@ -787,7 +788,9 @@ export class CollectionSchemaView extends CollectionSubView() {
     @action
     onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
         if (de.complete.columnDragData) {
-            setTimeout(() => {this.setColDrag(false);});
+            setTimeout(() => {
+                this.setColDrag(false);
+            });
             e.stopPropagation();
             return true;
         }
@@ -849,9 +852,9 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     @action
-    setKey = (key: string, defaultVal?: any, index?: number) => {
+    setKey = (key: string, defaultVal?: string, index?: number) => {
         if (this.columnKeys.includes(key)) return;
-    
+
         if (this._makeNewColumn) {
             this.addColumn(this.columnKeys.indexOf(key), key, defaultVal);
             this._makeNewColumn = false;
@@ -861,14 +864,14 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     /**
-     * Used in SchemaRowBox to set 
-     * @param key 
-     * @param value 
-     * @returns 
+     * Used in SchemaRowBox to set
+     * @param key
+     * @param value
+     * @returns
      */
     setCellValues = (key: string, value: string) => {
-        if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); 
-        else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value)); 
+        if (this._selectedCells.length === 1) this.docs.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value));
+        else this._selectedCells.forEach(doc => !doc._lockedSchemaEditing && Doc.SetField(doc, key, value));
         return true;
     };
 
@@ -912,34 +915,36 @@ export class CollectionSchemaView extends CollectionSubView() {
         const cm = ContextMenu.Instance;
         cm.clearItems();
 
-        const fieldSortedAsc = (this.sortField === this.columnKeys[index] && !this.sortDesc);
-        const fieldSortedDesc = (this.sortField === this.columnKeys[index] && this.sortDesc);
-        const revealOptions = cm.findByDescription('Sort column')
-        const sortOptions: ContextMenuProps[] = revealOptions && revealOptions && 'subitems' in revealOptions ? revealOptions.subitems ?? [] : [];
+        const fieldSortedAsc = this.sortField === this.columnKeys[index] && !this.sortDesc;
+        const fieldSortedDesc = this.sortField === this.columnKeys[index] && this.sortDesc;
+        const revealOptions = cm.findByDescription('Sort column');
+        const sortOptions: ContextMenuProps[] = revealOptions && revealOptions && 'subitems' in revealOptions ? (revealOptions.subitems ?? []) : [];
         sortOptions.push({
-            description: 'Sort A-Z',     
+            description: 'Sort A-Z',
             event: () => {
-                this.setColumnSort(undefined); 
+                this.setColumnSort(undefined);
                 const field = this.columnKeys[index];
                 this._containedDocs = this.sortDocs(field, false);
                 setTimeout(() => {
                     this.highlightSortedColumn(field, false);
-                    setTimeout(() => this.highlightSortedColumn(), 480); 
+                    setTimeout(() => this.highlightSortedColumn(), 480);
                 }, 20);
-            },     
-            icon: 'arrow-down-a-z',});
+            },
+            icon: 'arrow-down-a-z',
+        });
         sortOptions.push({
-            description: 'Sort Z-A',     
+            description: 'Sort Z-A',
             event: () => {
-                this.setColumnSort(undefined); 
+                this.setColumnSort(undefined);
                 const field = this.columnKeys[index];
                 this._containedDocs = this.sortDocs(field, true);
                 setTimeout(() => {
                     this.highlightSortedColumn(field, true);
-                    setTimeout(() => this.highlightSortedColumn(), 480); 
+                    setTimeout(() => this.highlightSortedColumn(), 480);
                 }, 20);
-            },     
-            icon: 'arrow-up-z-a'});
+            },
+            icon: 'arrow-up-z-a',
+        });
         sortOptions.push({
             description: 'Persistent Sort A-Z',     
             event: () => {
@@ -964,7 +969,7 @@ export class CollectionSchemaView extends CollectionSubView() {
                 }
             },     
             icon: fieldSortedDesc ? 'lock' : 'lock-open'}); // prettier-ignore
-    
+
         cm.addItem({
             description: `Change field`,
             event: () => this.openNewColumnMenu(index, false),
@@ -975,12 +980,12 @@ export class CollectionSchemaView extends CollectionSubView() {
             event: () => this.openFilterMenu(index),
             icon: 'filter',
         });
-        cm.addItem({ 
-            description: 'Sort column', 
-            addDivider: false, 
-            noexpand: true, 
-            subitems: sortOptions, 
-            icon: 'sort' 
+        cm.addItem({
+            description: 'Sort column',
+            addDivider: false,
+            noexpand: true,
+            subitems: sortOptions,
+            icon: 'sort',
         });
         cm.addItem({
             description: 'Add column to left',
@@ -1068,7 +1073,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     @computed get renderColumnMenu() {
         const x = this._columnMenuIndex! === -1 ? 0 : this.displayColumnWidths.reduce((total, curr, index) => total + (index < this._columnMenuIndex! ? curr : 0), CollectionSchemaView._rowMenuWidth);
         return (
-            <div className="schema-column-menu" style={{ left: x,  maxWidth: `${Math.max(this._colEles[this._columnMenuIndex ?? 0].offsetWidth, 150)}px` }}>
+            <div className="schema-column-menu" style={{ left: x, maxWidth: `${Math.max(this._colEles[this._columnMenuIndex ?? 0].offsetWidth, 150)}px` }}>
                 {this.keysDropdown}
             </div>
         );
@@ -1095,13 +1100,7 @@ export class CollectionSchemaView extends CollectionSubView() {
             }
             return (
                 <div key={key} className="schema-filter-option">
-                    <input 
-                        type="checkbox"
-                        onPointerDown={e => e.stopPropagation()}
-                        onClick={e => e.stopPropagation()}
-                        onChange={e => Doc.setDocFilter(this.Document, columnKey, key, e.target.checked ? 'check' : 'remove')}
-                        checked={bool}
-                    />
+                    <input type="checkbox" onPointerDown={e => e.stopPropagation()} onClick={e => e.stopPropagation()} onChange={e => Doc.setDocFilter(this.Document, columnKey, key, e.target.checked ? 'check' : 'remove')} checked={bool} />
                     <span style={{ paddingLeft: 4 }}>{key}</span>
                 </div>
             );
@@ -1111,7 +1110,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     @computed get renderFilterMenu() {
         const x = this.displayColumnWidths.reduce((total, curr, index) => total + (index < this._filterColumnIndex! ? curr : 0), CollectionSchemaView._rowMenuWidth);
         return (
-            <div className="schema-filter-menu" style={{ left: x, maxWidth: `${Math.max(this._colEles[this._columnMenuIndex ?? 0].offsetWidth, 150)}px`}}>
+            <div className="schema-filter-menu" style={{ left: x, maxWidth: `${Math.max(this._colEles[this._columnMenuIndex ?? 0].offsetWidth, 150)}px` }}>
                 <input className="schema-filter-input" type="text" value={this._filterSearchValue} onKeyDown={this.onFilterKeyDown} onChange={this.updateFilterSearch} onPointerDown={e => e.stopPropagation()} />
                 {this.renderFilterOptions}
                 <div
@@ -1129,13 +1128,13 @@ export class CollectionSchemaView extends CollectionSubView() {
     @action setColDrag = (beingDragged: boolean) => {
         this._colBeingDragged = beingDragged;
         !beingDragged && this.removeDragHighlight();
-    }
+    };
 
     @action updateMouseCoordinates = (e: React.PointerEvent<HTMLDivElement>) => {
         const prevX = this._mouseCoordinates.x;
         const prevY = this._mouseCoordinates.y;
         this._mouseCoordinates = { x: e.clientX, y: e.clientY, prevX: prevX, prevY: prevY };
-    }
+    };
 
     @action
     onPointerMove = (e: React.PointerEvent<HTMLDivElement>) => {
@@ -1158,9 +1157,9 @@ export class CollectionSchemaView extends CollectionSubView() {
 
     /**
      * Gets docs contained by collections within the schema. Currently defunct.
-     * @param doc 
-     * @param displayed 
-     * @returns 
+     * @param doc
+     * @param displayed
+     * @returns
      */
     // subCollectionDocs = (doc: Doc, displayed: boolean) => {
     //     const childDocs = DocListCast(doc[Doc.LayoutFieldKey(doc)]);
@@ -1203,8 +1202,7 @@ export class CollectionSchemaView extends CollectionSubView() {
                             subDocs.forEach(t => {
                                 const docFieldKey = Doc.LayoutFieldKey(t);
                                 const isSubDocAnnotatable = t[docFieldKey] instanceof List && !(t[docFieldKey] as List<Doc>)?.some(ele => !(ele instanceof Doc));
-                                notFiltered =
-                                    notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!childDocFilters.length && !childFiltersByRanges.length) || DocUtils.FilterDocs([t], childDocFilters, childFiltersByRanges, d).length));
+                                notFiltered = notFiltered || ((!searchDocs.length || searchDocs.includes(t)) && ((!childDocFilters.length && !childFiltersByRanges.length) || DocUtils.FilterDocs([t], childDocFilters, childFiltersByRanges, d).length));
                                 DocListCast(t[isSubDocAnnotatable ? docFieldKey + '_annotations' : docFieldKey]).forEach(newdoc => newarray.push(newdoc));
                                 isSubDocAnnotatable && DocListCast(t[docFieldKey + '_sidebar']).forEach(newdoc => newarray.push(newdoc));
                             });
@@ -1231,19 +1229,19 @@ export class CollectionSchemaView extends CollectionSubView() {
         //     docsFromChildren = docsFromChildren.concat(docsNotAlreadyDisplayed);
         // });
 
-        return this.filteredDocs;;
+        return this.filteredDocs;
     }
 
     /**
-     * Sorts docs first alphabetically and then numerically. 
+     * Sorts docs first alphabetically and then numerically.
      * @param field the column being sorted
      * @param desc whether the sort is ascending or descending
      * @param persistent whether the sort is applied persistently or is one-shot
-     * @returns 
+     * @returns
      */
     sortDocs = (field: string, desc: boolean, persistent?: boolean) => {
         const numbers: Doc[] = [];
-        const strings: Doc[] = []; 
+        const strings: Doc[] = [];
 
         this.docs.forEach(doc => {
             if (!isNaN(Number(Field.toString(doc[field] as FieldType)))) numbers.push(doc);
@@ -1253,25 +1251,26 @@ export class CollectionSchemaView extends CollectionSubView() {
         const sortedNums = numbers.sort((numOne, numTwo) => {
             const numA = Number(Field.toString(numOne[field] as FieldType));
             const numB = Number(Field.toString(numTwo[field] as FieldType));
-            return desc? numA - numB : numB - numA;
+            return desc ? numA - numB : numB - numA;
         });
 
-        const collator = new Intl.Collator(undefined, {sensitivity: 'base'});
+        const collator = new Intl.Collator(undefined, { sensitivity: 'base' });
         let sortedStrings;
-        if (!desc) {sortedStrings = strings.slice().sort((docA, docB) => collator.compare(Field.toString(docA[field] as FieldType), Field.toString(docB[field] as FieldType)));
+        if (!desc) {
+            sortedStrings = strings.slice().sort((docA, docB) => collator.compare(Field.toString(docA[field] as FieldType), Field.toString(docB[field] as FieldType)));
         } else sortedStrings = strings.slice().sort((docB, docA) => collator.compare(Field.toString(docA[field] as FieldType), Field.toString(docB[field] as FieldType)));
 
         const sortedDocs = desc ? sortedNums.concat(sortedStrings) : sortedStrings.concat(sortedNums);
         if (!persistent) this._containedDocs = sortedDocs;
         return sortedDocs;
-    }
-    
+    };
+
     /**
      * Returns all docs minus those currently being dragged by the user.
      */
     @computed get docsWithDrag() {
         let docs = this.docs.slice();
-        if (this.sortField){
+        if (this.sortField) {
             const field = StrCast(this.layoutDoc.sortField);
             const desc = BoolCast(this.layoutDoc.sortDesc); // is this an ascending or descending sort
             docs = this.sortDocs(field, desc, true);
@@ -1290,13 +1289,17 @@ export class CollectionSchemaView extends CollectionSubView() {
     previewWidthFunc = () => this.previewWidth;
     onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
     displayedDocsFunc = () => this.docsWithDrag.docs;
-    _oldWheel: any;
     render() {
         return (
-            <div className="collectionSchemaView" ref={(ele: HTMLDivElement | null) => this.createDashEventsTarget(ele)} 
-            onDrop={this.onExternalDrop.bind(this)} 
-            onPointerMove={e => this.onPointerMove(e)} 
-            onPointerDown={() => {this.closeNewColumnMenu(); this.setColDrag(false)}}>
+            <div
+                className="collectionSchemaView"
+                ref={(ele: HTMLDivElement | null) => this.createDashEventsTarget(ele)}
+                onDrop={this.onExternalDrop.bind(this)}
+                onPointerMove={e => this.onPointerMove(e)}
+                onPointerDown={() => {
+                    this.closeNewColumnMenu();
+                    this.setColDrag(false);
+                }}>
                 <div ref={this._menuTarget} style={{ background: 'red', top: 0, left: 0, position: 'absolute', zIndex: 10000 }} />
                 <div
                     className="schema-table"
@@ -1310,30 +1313,29 @@ export class CollectionSchemaView extends CollectionSubView() {
                     <div className="schema-header-row" style={{ height: this.rowHeightFunc() }}>
                         <div className="row-menu" style={{ width: CollectionSchemaView._rowMenuWidth }}>
                             <IconButton
-                            tooltip="Add a new key"
-                            icon={ <FontAwesomeIcon icon="plus" size='lg'/>}
-                            size={Size.XSMALL}
-                            color={'black'}
-                            onPointerDown={e =>
-                                setupMoveUpEvents(
-                                    this,
-                                    e,
-                                    returnFalse,
-                                    emptyFunction,
-                                    undoable(clickEv => {
-                                        clickEv.stopPropagation();
-                                        this.addColumn()
-                                    }, 'add key to schema')
-                                )
-                            }
+                                tooltip="Add a new key"
+                                icon={<FontAwesomeIcon icon="plus" size="lg" />}
+                                size={Size.XSMALL}
+                                color={'black'}
+                                onPointerDown={e =>
+                                    setupMoveUpEvents(
+                                        this,
+                                        e,
+                                        returnFalse,
+                                        emptyFunction,
+                                        undoable(clickEv => {
+                                            clickEv.stopPropagation();
+                                            this.addColumn();
+                                        }, 'add key to schema')
+                                    )
+                                }
                             />
                         </div>
                         {this.columnKeys.map((key, index) => (
                             <SchemaColumnHeader
-                                // eslint-disable-next-line react/no-array-index-key
                                 //cleanupField={this.cleanupComputedField}
                                 ref={r => r && this._headerRefs.push(r)}
-                                keysDropdown={(this.keysDropdown)}
+                                keysDropdown={this.keysDropdown}
                                 schemaView={this}
                                 columnWidth={() => CollectionSchemaView._minColWidth} //TODO: update
                                 Document={this.Document}
@@ -1445,7 +1447,6 @@ class CollectionSchemaViewDoc extends ObservableReactComponent<CollectionSchemaV
         return (
             <DocumentView
                 key={this._props.doc[Id]}
-                // eslint-disable-next-line react/jsx-props-no-spreading
                 {...this._props.schema._props}
                 containerViewPath={this._props.schema.childContainerViewPath}
                 LayoutTemplate={this._props.schema._props.childLayoutTemplate}
@@ -1498,4 +1499,4 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP
             </div>
         );
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
index c5cdac8af..47918f9c1 100644
--- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable react/no-unused-prop-types */
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, makeObservable, observable } from 'mobx';
 import { observer } from 'mobx-react';
@@ -21,7 +20,8 @@ import { undoable } from '../../../util/UndoManager';
 import { IconButton, Size } from 'browndash-components';
 
 export enum SchemaFieldType {
-    Header, Cell
+    Header,
+    Cell,
 }
 
 export interface SchemaColumnHeaderProps {
@@ -49,7 +49,6 @@ export interface SchemaColumnHeaderProps {
 
 @observer
 export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHeaderProps> {
-
     private _inputRef: EditableView | null = null;
     @observable _altTitle: string | undefined = undefined;
     @observable _showMenuIcon: boolean = false;
@@ -58,18 +57,26 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
         return this._props.columnKeys[this._props.columnIndex];
     }
 
-    constructor(props: SchemaColumnHeaderProps){
+    constructor(props: SchemaColumnHeaderProps) {
         super(props);
         makeObservable(this);
     }
-    
+
     getFinfo = computedFn((fieldKey: string) => this._props.schemaView?.fieldInfos.get(fieldKey));
-    setColumnValues = (field: string, defaultValue: string) => {this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);}
-    @action updateAlt = (newAlt: string) => {this._altTitle = newAlt};
-    updateKeyDropdown = (value: string) => {this._props.schemaView.updateKeySearch(value)};
-    openKeyDropdown = () => {!this._props.schemaView._colBeingDragged && this._props.schemaView.openNewColumnMenu(this._props.columnIndex, false)};
+    setColumnValues = (field: string, defaultValue: string) => {
+        this._props.schemaView?.setKey(field, defaultValue, this._props.columnIndex);
+    };
+    @action updateAlt = (newAlt: string) => {
+        this._altTitle = newAlt;
+    };
+    updateKeyDropdown = (value: string) => {
+        this._props.schemaView.updateKeySearch(value);
+    };
+    openKeyDropdown = () => {
+        !this._props.schemaView._colBeingDragged && this._props.schemaView.openNewColumnMenu(this._props.columnIndex, false);
+    };
     toggleEditing = (editing: boolean) => {
-        this._inputRef?.setIsEditing(editing); 
+        this._inputRef?.setIsEditing(editing);
         this._inputRef?.setIsFocused(editing);
     };
 
@@ -110,139 +117,156 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea
         const cursor = !readOnly ? 'text' : 'default';
         const pointerEvents: 'all' | 'none' = 'all';
         return { color, fieldProps, cursor, pointerEvents };
-    }
+    };
 
     @computed get editableView() {
-        const { color, fieldProps, pointerEvents } = this.renderProps(this._props); 
-
-        return <div className='schema-column-edit-wrapper' onPointerUp={() => {
-            SchemaColumnHeader.isDefaultField(this.fieldKey) && this.openKeyDropdown();
-            this._props.schemaView.deselectAllCells();
-        }}
-        style={{
-            color,
-            width: '100%',
-            pointerEvents,
-        }}>
-            <EditableView
-                ref={r => {this._inputRef = r; this._props.autoFocus && r?.setIsFocused(true)}}
-                oneLine={true}
-                allowCRs={false}
-                contents={''}
-                onClick={this.openKeyDropdown}
-                fieldContents={fieldProps}
-                editing={undefined}  
-                placeholder={'Add key'}
-                updateAlt={this.updateAlt} // alternate title to display
-                updateSearch={this.updateKeyDropdown}
-                schemaFieldType={SchemaFieldType.Header} 
-                GetValue={() => {
-                    if (SchemaColumnHeader.isDefaultField(this.fieldKey)) return '';
-                    else if (this._altTitle) return this._altTitle;
-                    else return this.fieldKey;
+        const { color, fieldProps, pointerEvents } = this.renderProps(this._props);
+
+        return (
+            <div
+                className="schema-column-edit-wrapper"
+                onPointerUp={() => {
+                    SchemaColumnHeader.isDefaultField(this.fieldKey) && this.openKeyDropdown();
+                    this._props.schemaView.deselectAllCells();
                 }}
-                SetValue={undoable((value: string, shiftKey?: boolean, enterKey?: boolean) => {
-                    if (enterKey) { // if shift & enter, set value of each cell in column
-                        this.setColumnValues(value, '');
-                        this._altTitle = undefined;
+                style={{
+                    color,
+                    width: '100%',
+                    pointerEvents,
+                }}>
+                <EditableView
+                    ref={r => {
+                        this._inputRef = r;
+                        this._props.autoFocus && r?.setIsFocused(true);
+                    }}
+                    oneLine={true}
+                    allowCRs={false}
+                    contents={''}
+                    onClick={this.openKeyDropdown}
+                    fieldContents={fieldProps}
+                    editing={undefined}
+                    placeholder={'Add key'}
+                    updateAlt={this.updateAlt} // alternate title to display
+                    updateSearch={this.updateKeyDropdown}
+                    schemaFieldType={SchemaFieldType.Header}
+                    GetValue={() => {
+                        if (SchemaColumnHeader.isDefaultField(this.fieldKey)) return '';
+                        else if (this._altTitle) return this._altTitle;
+                        else return this.fieldKey;
+                    }}
+                    SetValue={undoable((value: string, shiftKey?: boolean, enterKey?: boolean) => {
+                        if (enterKey) {
+                            // if shift & enter, set value of each cell in column
+                            this.setColumnValues(value, '');
+                            this._altTitle = undefined;
+                            this._props.finishEdit?.();
+                            return true;
+                        }
                         this._props.finishEdit?.();
                         return true;
-                    }
-                    this._props.finishEdit?.(); 
-                    return true;
-                }, 'edit column header')}
-            />
+                    }, 'edit column header')}
+                />
             </div>
+        );
     }
 
     public static isDefaultField = (key: string) => {
         const defaultPattern = /EmptyColumnKey/;
-        const isDefault: boolean = (defaultPattern.exec(key) != null);
+        const isDefault: boolean = defaultPattern.exec(key) != null;
         return isDefault;
-    }
+    };
 
-    get headerButton(){
-        const toRender = SchemaColumnHeader.isDefaultField(this.fieldKey) ? 
-        (<IconButton
-            icon={ <FontAwesomeIcon icon="trash" size='sm'/>}
-            size={Size.XSMALL}
-            color={'black'}
-            onPointerDown={e =>
-                setupMoveUpEvents(
-                    this,
-                    e,
-                    returnFalse,
-                    emptyFunction,
-                    undoable(clickEv => {
-                        clickEv.stopPropagation();
-                        this._props.schemaView.removeColumn(this._props.columnIndex);
-                    }, 'open column menu')
-                )
-            }
-        />)
-        : (<IconButton
-            icon={ <FontAwesomeIcon icon="caret-down" size='lg'/>}
-            size={Size.XSMALL}
-            color={'black'}
-            onPointerDown={e =>
-                setupMoveUpEvents(
-                    this,
-                    e,
-                    returnFalse,
-                    emptyFunction,
-                    undoable(clickEv => {
-                        clickEv.stopPropagation();
-                        this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)
-                    }, 'open column menu')
-                )
-            }
-        />)
+    get headerButton() {
+        const toRender = SchemaColumnHeader.isDefaultField(this.fieldKey) ? (
+            <IconButton
+                icon={<FontAwesomeIcon icon="trash" size="sm" />}
+                size={Size.XSMALL}
+                color={'black'}
+                onPointerDown={e =>
+                    setupMoveUpEvents(
+                        this,
+                        e,
+                        returnFalse,
+                        emptyFunction,
+                        undoable(clickEv => {
+                            clickEv.stopPropagation();
+                            this._props.schemaView.removeColumn(this._props.columnIndex);
+                        }, 'open column menu')
+                    )
+                }
+            />
+        ) : (
+            <IconButton
+                icon={<FontAwesomeIcon icon="caret-down" size="lg" />}
+                size={Size.XSMALL}
+                color={'black'}
+                onPointerDown={e =>
+                    setupMoveUpEvents(
+                        this,
+                        e,
+                        returnFalse,
+                        emptyFunction,
+                        undoable(clickEv => {
+                            clickEv.stopPropagation();
+                            this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex);
+                        }, 'open column menu')
+                    )
+                }
+            />
+        );
 
         return toRender;
     }
 
-    @action handlePointerEnter = () => this._showMenuIcon = true;
-    @action handlePointerLeave = () => this._showMenuIcon = false;
+    @action handlePointerEnter = () => { this._showMenuIcon = true; } // prettier-ignore
+    @action handlePointerLeave = () => { this._showMenuIcon = false; } // prettier-ignore
 
-    @computed get displayButton() {return this._showMenuIcon;}
+    @computed get displayButton() {
+        return this._showMenuIcon;
+    }
 
     render() {
         return (
-                <div
-                    className="schema-column-header"
-                    style={{
-                        width: this._props.columnWidths[this._props.columnIndex],
-                    }}
-                    onPointerEnter={() => {this.handlePointerEnter()}}
-                    onPointerLeave={() => {this.handlePointerLeave()}}
-                    onPointerDown={e => {
-                        this.setupDrag(e);
-                        setupMoveUpEvents(
-                            this,
-                            e,
-                            () => {return this._inputRef?.setIsEditing(false) ?? false},
-                            emptyFunction,
-                            emptyFunction,
-                            );
-                        }
+            <div
+                className="schema-column-header"
+                style={{
+                    width: this._props.columnWidths[this._props.columnIndex],
+                }}
+                onPointerEnter={() => {
+                    this.handlePointerEnter();
+                }}
+                onPointerLeave={() => {
+                    this.handlePointerLeave();
+                }}
+                onPointerDown={e => {
+                    this.setupDrag(e);
+                    setupMoveUpEvents(
+                        this,
+                        e,
+                        () => {
+                            return this._inputRef?.setIsEditing(false) ?? false;
+                        },
+                        emptyFunction,
+                        emptyFunction
+                    );
+                }}
+                ref={col => {
+                    if (col) {
+                        this._props.setColRef(this._props.columnIndex, col);
                     }
-                    ref={col => {
-                        if (col) {
-                            this._props.setColRef(this._props.columnIndex, col);
-                        }
-                    }}>
-                    <div className="schema-column-resizer left" onPointerDown={e => this._props.resizeColumn(e, this._props.columnIndex, false)} />
+                }}>
+                <div className="schema-column-resizer left" onPointerDown={e => this._props.resizeColumn(e, this._props.columnIndex, false)} />
 
-                    <div className="schema-header-text">{this.editableView}</div>
+                <div className="schema-header-text">{this.editableView}</div>
 
-                    <div className="schema-header-menu">
-                        <div className="schema-header-button" style={{opacity: this.displayButton ? '1.0' : '0.0'}}>
-                            {this.headerButton}
-                        </div>
-                    </div>  
-
-                    <div className="schema-column-resizer right" onPointerDown={e => this._props.resizeColumn(e, this._props.columnIndex, true)} />
+                <div className="schema-header-menu">
+                    <div className="schema-header-button" style={{ opacity: this.displayButton ? '1.0' : '0.0' }}>
+                        {this.headerButton}
+                    </div>
                 </div>
+
+                <div className="schema-column-resizer right" onPointerDown={e => this._props.resizeColumn(e, this._props.columnIndex, true)} />
+            </div>
         );
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
index a8a4ef2c2..6ffb0865a 100644
--- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx
@@ -21,7 +21,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core';
 
 /**
  * The SchemaRowBox renders a doc as a row of cells, with each cell representing
- * one field value of the doc. It mostly handles communication from the SchemaView 
+ * one field value of the doc. It mostly handles communication from the SchemaView
  * to each SchemaCell, passing down necessary functions are props.
  */
 
@@ -59,7 +59,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         ContextMenu.Instance.clearItems();
         ContextMenu.Instance.addItem({
             description: this.Document._lockedSchemaEditing ? 'Unlock field editing' : 'Lock field editing',
-            event: () => this.Document._lockedSchemaEditing = !this.Document._lockedSchemaEditing,
+            event: () => (this.Document._lockedSchemaEditing = !this.Document._lockedSchemaEditing),
             icon: this.Document._lockedSchemaEditing ? 'lock-open' : 'lock',
         });
         ContextMenu.Instance.addItem({
@@ -78,17 +78,19 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         //         ContextMenu.Instance.addItem({
         //         description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema',
         //         event: () => {
-        //             this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; 
+        //             this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema;
         //         },
         //         icon: this.Document._childrenSharedWithSchema ? 'minus' : 'plus',
         //     });
         // }
         ContextMenu.Instance.displayMenu(x, y, undefined, false);
-    }
+    };
 
-    @computed get menuBackgroundColor(){
-        if (this.Document._lockedSchemaEditing) {return '#F5F5F5'}   
-        return ''
+    @computed get menuBackgroundColor() {
+        if (this.Document._lockedSchemaEditing) {
+            return '#F5F5F5';
+        }
+        return '';
     }
 
     @computed get menuInfos() {
@@ -98,22 +100,28 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
         return infos;
     }
 
-    isolatedSelection = (doc: Doc) => {return this.schemaView?.selectionOverlap(doc)};
+    isolatedSelection = (doc: Doc) => {
+        return this.schemaView?.selectionOverlap(doc);
+    };
     setCursorIndex = (mouseY: number) => this.schemaView?.setRelCursorIndex(mouseY);
     selectedCol = () => this.schemaView._selectedCol;
     getFinfo = computedFn((fieldKey: string) => this.schemaView?.fieldInfos.get(fieldKey));
     selectCell = (doc: Doc, col: number, shift: boolean, ctrl: boolean) => this.schemaView?.selectCell(doc, col, shift, ctrl);
     deselectCell = () => this.schemaView?.deselectAllCells();
     selectedCells = () => this.schemaView?._selectedDocs;
-    setColumnValues = (field: any, value: any) => this.schemaView?.setCellValues(field, value) ?? false;
+    setColumnValues = (field: string, value: string) => this.schemaView?.setCellValues(field, value) ?? false;
     columnWidth = computedFn((index: number) => () => this.schemaView?.displayColumnWidths[index] ?? CollectionSchemaView._minColWidth);
     computeRowIndex = () => this.schemaView?.rowIndex(this.Document);
     highlightCells = (text: string) => this.schemaView?.highlightCells(text);
-    selectReference = (doc: Doc, col: number) => {this.schemaView.selectReference(doc, col)}
+    selectReference = (doc: Doc, col: number) => {
+        this.schemaView.selectReference(doc, col);
+    };
     eqHighlightFunc = (text: string) => {
         const info = this.schemaView.findCellRefs(text);
         const cells: HTMLDivElement[] = [];
-        info.forEach(info => {cells.push(this.schemaView.getCellElement(info[0], info[1]))})
+        info.forEach(inf => {
+            cells.push(this.schemaView.getCellElement(inf[0], inf[1]));
+        });
         return cells;
     };
     render() {
@@ -121,7 +129,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
             <div
                 className="schema-row"
                 onPointerDown={e => this.setCursorIndex(e.clientY)}
-                style={{ height: this._props.PanelHeight()}}
+                style={{ height: this._props.PanelHeight() }}
                 ref={(row: HTMLDivElement | null) => {
                     row && this.schemaView?.addRowRef?.(this.Document, row);
                     this._ref = row;
@@ -131,11 +139,11 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                     style={{
                         width: CollectionSchemaView._rowMenuWidth,
                         pointerEvents: !this._props.isContentActive() ? 'none' : undefined,
-                        backgroundColor: this.menuBackgroundColor
+                        backgroundColor: this.menuBackgroundColor,
                     }}>
                     <IconButton
                         tooltip="Open actions menu"
-                        icon={ <FontAwesomeIcon icon="caret-right" size='lg'/>}
+                        icon={<FontAwesomeIcon icon="caret-right" size="lg" />}
                         size={Size.XSMALL}
                         color={'black'}
                         onPointerDown={e =>
@@ -146,14 +154,16 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
                                 emptyFunction,
                                 undoable(clickEv => {
                                     clickEv.stopPropagation();
-                                    this.openContextMenu(e.clientX, e.clientY)
+                                    this.openContextMenu(e.clientX, e.clientY);
                                 }, 'open actions menu')
                             )
                         }
                     />
-                <div className="row-menu-infos">
-                    {this.menuInfos.map(icn => <FontAwesomeIcon className="row-infos-icon" icon={icn} size='2xs' />)}
-                </div>
+                    <div className="row-menu-infos">
+                        {this.menuInfos.map(icn => (
+                            <FontAwesomeIcon key={icn.toString()} className="row-infos-icon" icon={icn} size="2xs" />
+                        ))}
+                    </div>
                 </div>
                 <div className="row-cells">
                     {this.schemaView?.columnKeys?.map((key, index) => (
@@ -192,4 +202,4 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() {
             </div>
         );
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
index c05382ce0..f036ff843 100644
--- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
+++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable react/jsx-props-no-spreading */
 /* eslint-disable no-use-before-define */
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Popup, Size, Type } from 'browndash-components';
@@ -37,7 +36,7 @@ import { SchemaCellField } from './SchemaCellField';
 /**
  * SchemaTableCells make up the majority of the visual representation of the SchemaView.
  * They are rendered for each cell in the SchemaView, and each represents one field value
- * of a doc. Editing the content of the cell changes the corresponding doc's field value. 
+ * of a doc. Editing the content of the cell changes the corresponding doc's field value.
  */
 
 export interface SchemaTableCellProps {
@@ -67,21 +66,16 @@ export interface SchemaTableCellProps {
     isolatedSelection: (doc: Doc) => [boolean, boolean];
     highlightCells: (text: string) => void;
     eqHighlightFunc: (text: string) => HTMLDivElement[] | [];
-    refSelectModeInfo: {enabled: boolean, currEditing: SchemaCellField | undefined};
+    refSelectModeInfo: { enabled: boolean; currEditing: SchemaCellField | undefined };
     selectReference: (doc: Doc, col: number) => void;
 }
 
 function selectedCell(props: SchemaTableCellProps) {
-    return (
-        props.isRowActive() &&
-        props.selectedCol() === props.col && 
-        props.selectedCells()?.filter(d => d === props.Document)?.length
-    );
+    return props.isRowActive() && props.selectedCol() === props.col && props.selectedCells()?.filter(d => d === props.Document)?.length;
 }
 
 @observer
 export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellProps> {
-
     // private _fieldRef: SchemaCellField | null = null;
     private _submittedValue: string = '';
 
@@ -96,9 +90,11 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
 
     get lockedInteraction(){return (this.isDefault || this._props.Document._lockedSchemaEditing);} // prettier-ignore
 
-    get backgroundColor(){
-        if (this.lockedInteraction) {return '#F5F5F5'}   
-        return ''
+    get backgroundColor() {
+        if (this.lockedInteraction) {
+            return '#F5F5F5';
+        }
+        return '';
     }
 
     static addFieldDoc = (docs: Doc | Doc[] /* , where: OpenWhere */) => {
@@ -110,7 +106,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         let protoCount = 0;
         let doc: Doc | undefined = Document;
         while (doc) {
-            if (Object.keys(doc).includes(fieldKey.replace(/^_/, ''))) break; 
+            if (Object.keys(doc).includes(fieldKey.replace(/^_/, ''))) break;
             protoCount++;
             doc = DocCast(doc.proto);
         }
@@ -149,28 +145,40 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
     adjustSelfReference = (field: string) => {
         const modField = field.replace(/\bthis.\b/g, `d${this.docIndex}.`);
         return modField;
-    }
+    };
 
     // parses a field from the "idToDoc(####)" format to DocumentId (d#) format for readability
     cleanupField = (field: string) => {
         let modField = field.slice();
         let eqSymbol: string = '';
-        if (modField.startsWith('=')) {modField = modField.substring(1); eqSymbol += '=';}
-        if (modField.startsWith(':=')) {modField = modField.substring(2); eqSymbol += ':=';}
+        if (modField.startsWith('=')) {
+            modField = modField.substring(1);
+            eqSymbol += '=';
+        }
+        if (modField.startsWith(':=')) {
+            modField = modField.substring(2);
+            eqSymbol += ':=';
+        }
 
         const idPattern = /idToDoc\((.*?)\)/g;
         let matches;
         const results = new Array<[id: string, func: string]>();
-        while ((matches = idPattern.exec(field)) !== null) {results.push([matches[0], matches[1].replace(/"/g, '')]); }
-        results.forEach((idFuncPair) => {modField = modField.replace(idFuncPair[0], 'd' + (DocumentView.getDocViewIndex(IdToDoc(idFuncPair[1]))).toString());})
+        while ((matches = idPattern.exec(field)) !== null) {
+            results.push([matches[0], matches[1].replace(/"/g, '')]);
+        }
+        results.forEach(idFuncPair => {
+            modField = modField.replace(idFuncPair[0], 'd' + DocumentView.getDocViewIndex(IdToDoc(idFuncPair[1])).toString());
+        });
 
         if (modField.endsWith(';')) modField = modField.substring(0, modField.length - 1);
 
-        const inQuotes = (field: string) => {return ((field.startsWith('`') && field.endsWith('`')) || (field.startsWith("'") && field.endsWith("'")) || (field.startsWith('"') && field.endsWith('"')))}
+        const inQuotes = (strField: string) => {
+            return (strField.startsWith('`') && strField.endsWith('`')) || (strField.startsWith("'") && strField.endsWith("'")) || (strField.startsWith('"') && strField.endsWith('"'));
+        };
         if (!inQuotes(this._submittedValue) && inQuotes(modField)) modField = modField.substring(1, modField.length - 1);
 
         return eqSymbol + modField;
-    }
+    };
 
     @computed get defaultCellContent() {
         const { color, textDecoration, fieldProps, pointerEvents } = SchemaTableCell.renderProps(this._props);
@@ -203,7 +211,7 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                             this._props.finishEdit?.();
                             return true;
                         }
-                        const hasNoLayout =  Doc.IsDataProto(fieldProps.Document) ? true : undefined; // the "delegate" is a a data document so never write to it's proto
+                        const hasNoLayout = Doc.IsDataProto(fieldProps.Document) ? true : undefined; // the "delegate" is a a data document so never write to it's proto
                         const ret = Doc.SetField(fieldProps.Document, this._props.fieldKey.replace(/^_/, ''), value, hasNoLayout);
                         this._submittedValue = value;
                         this._props.finishEdit?.();
@@ -245,8 +253,8 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
         const sides: Array<string | undefined> = [];
         sides[0] = selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // left
         sides[1] = selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // right
-        sides[2] = (!this._props.isolatedSelection(this._props.Document)[0] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // top
-        sides[3] = (!this._props.isolatedSelection(this._props.Document)[1] && selectedCell(this._props)) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // bottom
+        sides[2] = !this._props.isolatedSelection(this._props.Document)[0] && selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // top
+        sides[3] = !this._props.isolatedSelection(this._props.Document)[1] && selectedCell(this._props) ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined; // bottom
         return sides;
     }
 
@@ -256,9 +264,13 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                 className="schema-table-cell"
                 onContextMenu={e => StopEvent(e)}
                 onPointerDown={action(e => {
-                    if (this.lockedInteraction) { e.stopPropagation(); e.preventDefault(); return; }
+                    if (this.lockedInteraction) {
+                        e.stopPropagation();
+                        e.preventDefault();
+                        return;
+                    }
 
-                    if (this._props.refSelectModeInfo.enabled && !selectedCell(this._props)){
+                    if (this._props.refSelectModeInfo.enabled && !selectedCell(this._props)) {
                         e.stopPropagation();
                         e.preventDefault();
                         this._props.selectReference(this._props.Document, this._props.col);
@@ -274,14 +286,16 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro
                         } else !selectedCell(this._props) && this._props.selectCell(this._props.Document, this._props.col, shift, ctrl);
                     }
                 })}
-                style={{ padding: this._props.padding, 
-                maxWidth: this._props.maxWidth?.(), 
-                width: this._props.columnWidth() || undefined, 
-                borderLeft: this.borderColor[0],
-                borderRight: this.borderColor[1],
-                borderTop: this.borderColor[2],
-                borderBottom: this.borderColor[3],
-                backgroundColor: this.backgroundColor}}>
+                style={{
+                    padding: this._props.padding,
+                    maxWidth: this._props.maxWidth?.(),
+                    width: this._props.columnWidth() || undefined,
+                    borderLeft: this.borderColor[0],
+                    borderRight: this.borderColor[1],
+                    borderTop: this.borderColor[2],
+                    borderBottom: this.borderColor[3],
+                    backgroundColor: this.backgroundColor,
+                }}>
                 {this.isDefault ? '' : this.content}
             </div>
         );
@@ -524,4 +538,4 @@ export class SchemaEnumerationCell extends ObservableReactComponent<SchemaTableC
             </div>
         );
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
index 962a21dbb..6c3f4eaff 100644
--- a/src/client/views/global/globalScripts.ts
+++ b/src/client/views/global/globalScripts.ts
@@ -84,7 +84,6 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b
             } else {
                 const dataKey = Doc.LayoutFieldKey(dv.Document);
                 const alternate = (dv.layoutDoc[dataKey + '_usePath'] ? '_' + dv.layoutDoc[dataKey + '_usePath'] : '').replace(':hover', '');
-                console.log('color: ' + dv.dataDoc[fieldKey + alternate] + ' to set to: ' + color)
                 dv.layoutDoc[fieldKey + alternate] = undefined;
                 dv.dataDoc[fieldKey + alternate] = color;
             }
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index 12196f290..a44014444 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable react/jsx-props-no-spreading */
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Checkbox } from '@mui/material';
 import { Colors, Toggle, ToggleType, Type } from 'browndash-components';
@@ -8,42 +7,36 @@ import * as React from 'react';
 import { ClientUtils, returnEmptyString, returnFalse, returnOne, setupMoveUpEvents } from '../../../../ClientUtils';
 import { emptyFunction } from '../../../../Utils';
 import { Doc, DocListCast, Field, FieldType, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
+import { AclAdmin, AclAugment, AclEdit } from '../../../../fields/DocSymbols';
 import { InkTool } from '../../../../fields/InkField';
 import { List } from '../../../../fields/List';
+import { PrefetchProxy } from '../../../../fields/Proxy';
 import { Cast, CsvCast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
 import { CsvField } from '../../../../fields/URLField';
-import { GetEffectiveAcl, TraceMobx, inheritParentAcls } from '../../../../fields/util';
+import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util';
+import { GPTCallType, gptAPICall } from '../../../apis/gpt/GPT';
 import { DocUtils } from '../../../documents/DocUtils';
 import { DocumentType } from '../../../documents/DocumentTypes';
 import { Docs } from '../../../documents/Documents';
+import { LinkManager } from '../../../util/LinkManager';
 import { UndoManager, undoable } from '../../../util/UndoManager';
 import { ContextMenu } from '../../ContextMenu';
 import { ViewBoxAnnotatableComponent } from '../../DocComponent';
 import { MarqueeAnnotator } from '../../MarqueeAnnotator';
 import { PinProps } from '../../PinFuncs';
 import { SidebarAnnos } from '../../SidebarAnnos';
+import { CollectionFreeFormView } from '../../collections/collectionFreeForm';
 import { AnchorMenu } from '../../pdf/AnchorMenu';
 import { GPTPopup, GPTPopupMode } from '../../pdf/GPTPopup/GPTPopup';
 import { DocumentView } from '../DocumentView';
 import { FieldView, FieldViewProps } from '../FieldView';
 import { FocusViewOptions } from '../FocusViewOptions';
 import './DataVizBox.scss';
+import { Col, DataVizTemplateInfo, DocCreatorMenu, LayoutType, TemplateFieldSize, TemplateFieldType } from './DocCreatorMenu';
 import { Histogram } from './components/Histogram';
 import { LineChart } from './components/LineChart';
 import { PieChart } from './components/PieChart';
 import { TableBox } from './components/TableBox';
-import { LinkManager } from '../../../util/LinkManager';
-import { Col, DataVizTemplateInfo, DataVizTemplateLayout, DocCreatorMenu, TemplateFieldSize, LayoutType, TemplateFieldType } from './DocCreatorMenu';
-import { CollectionFreeFormView, MarqueeView } from '../../collections/collectionFreeForm';
-import { PrefetchProxy } from '../../../../fields/Proxy';
-import { AclAdmin, AclAugment, AclEdit } from '../../../../fields/DocSymbols';
-import { template } from 'lodash';
-import { data } from 'jquery';
-import { listSpec } from '../../../../fields/Schema';
-import { ObjectField } from '../../../../fields/ObjectField';
-import { Id } from '../../../../fields/FieldSymbols';
-import { GPTCallType, gptAPICall } from '../../../apis/gpt/GPT';
-import { TbSortDescendingShapes } from 'react-icons/tb';
 
 export enum DataVizView {
     TABLE = 'table',
@@ -65,7 +58,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     @observable _marqueeing: number[] | undefined = undefined;
     @observable _savedAnnotations = new ObservableMap<number, HTMLDivElement[]>();
     @observable _specialHighlightedRow: number | undefined = undefined;
-    @observable GPTSummary: ObservableMap<string, {desc?: string, type?: TemplateFieldType, size?: TemplateFieldSize}> | undefined = undefined;
+    @observable GPTSummary: ObservableMap<string, { desc?: string; type?: TemplateFieldType; size?: TemplateFieldSize }> | undefined = undefined;
     @observable colsInfo: ObservableMap<string, Col> = new ObservableMap();
     @observable _GPTLoading: boolean = false;
 
@@ -121,12 +114,9 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             const records = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey]).url.href);
             this._urlError = false;
             return records?.filter(record => Object.keys(record).some(key => record[key])) ?? [];
-        } catch (e){
+        } catch {
             this._urlError = true;
-            const data: { [key: string]: string; }[] = [
-                { error: "Data not found"},
-              ];          
-            return data;
+            return [{ error: 'Data not found' }] as { [key: string]: string }[];
         }
     }
 
@@ -153,70 +143,73 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
 
     @action setSpecialHighlightedRow = (row: number | undefined) => {
         this._specialHighlightedRow = row;
-    }
+    };
 
     @action setColumnType = (colTitle: string, type: TemplateFieldType) => {
         const colInfo = this.colsInfo.get(colTitle);
-        if (colInfo) { 
+        if (colInfo) {
             colInfo.type = type;
         } else {
-            this.colsInfo.set(colTitle, {title: colTitle, desc: '', type: type, sizes: [TemplateFieldSize.MEDIUM]})
+            this.colsInfo.set(colTitle, { title: colTitle, desc: '', type: type, sizes: [TemplateFieldSize.MEDIUM] });
         }
-    }
+    };
 
     @action modifyColumnSizes = (colTitle: string, size: TemplateFieldSize, valid: boolean) => {
         const column = this.colsInfo.get(colTitle);
-        if (column) { 
+        if (column) {
             if (!valid && column.sizes.includes(size)) {
                 column.sizes.splice(column.sizes.indexOf(size), 1);
             } else if (valid && !column.sizes.includes(size)) {
                 column.sizes.push(size);
             }
         } else {
-            this.colsInfo.set(colTitle, {title: colTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [size]})
+            this.colsInfo.set(colTitle, { title: colTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [size] });
         }
-    }
+    };
 
     @action setColumnTitle = (colTitle: string, newTitle: string) => {
         const colInfo = this.colsInfo.get(colTitle);
-        if (colInfo) { 
+        if (colInfo) {
             colInfo.title = newTitle;
-            console.log(colInfo.title)
+            console.log(colInfo.title);
         } else {
-            this.colsInfo.set(colTitle, {title: newTitle, desc: '', type: TemplateFieldType.UNSET, sizes: []})
+            this.colsInfo.set(colTitle, { title: newTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [] });
         }
-    }
+    };
 
     @action setColumnDesc = (colTitle: string, desc: string) => {
         const colInfo = this.colsInfo.get(colTitle);
         if (colInfo) {
-            if (!desc) { colInfo.desc = this.GPTSummary?.get(colTitle)?.desc ?? ''; } 
-            else { colInfo.desc = desc; }
+            if (!desc) {
+                colInfo.desc = this.GPTSummary?.get(colTitle)?.desc ?? '';
+            } else {
+                colInfo.desc = desc;
+            }
         } else {
-            this.colsInfo.set(colTitle, {title: colTitle, desc: desc, type: TemplateFieldType.UNSET, sizes: []})
+            this.colsInfo.set(colTitle, { title: colTitle, desc: desc, type: TemplateFieldType.UNSET, sizes: [] });
         }
-    }
+    };
 
     @action setColumnDefault = (colTitle: string, cont: string) => {
         const colInfo = this.colsInfo.get(colTitle);
         if (colInfo) {
             colInfo.defaultContent = cont;
         } else {
-            this.colsInfo.set(colTitle, {title: colTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [], defaultContent: cont})
+            this.colsInfo.set(colTitle, { title: colTitle, desc: '', type: TemplateFieldType.UNSET, sizes: [], defaultContent: cont });
         }
-    }
+    };
 
     @action // pinned / linked anchor doc includes selected rows, graph titles, and graph colors
-    restoreView = (data: Doc) => {
+    restoreView = (viewData: Doc) => {
         // const changedView = data.config_dataViz && this.dataVizView !== data.config_dataViz && (this.layoutDoc._dataViz = data.config_dataViz);
         // const changedAxes = data.config_dataVizAxes && this.axes.join('') !== StrListCast(data.config_dataVizAxes).join('') && (this.layoutDoc._dataViz_axes = new List<string>(StrListCast(data.config_dataVizAxes)));
-        this.layoutDoc.dataViz_selectedRows = Field.Copy(data.dataViz_selectedRows);
-        this.layoutDoc.dataViz_histogram_barColors = Field.Copy(data.dataViz_histogram_barColors);
-        this.layoutDoc.dataViz_histogram_defaultColor = data.dataViz_histogram_defaultColor;
-        this.layoutDoc.dataViz_pie_sliceColors = Field.Copy(data.dataViz_pie_sliceColors);
+        this.layoutDoc.dataViz_selectedRows = Field.Copy(viewData.dataViz_selectedRows);
+        this.layoutDoc.dataViz_histogram_barColors = Field.Copy(viewData.dataViz_histogram_barColors);
+        this.layoutDoc.dataViz_histogram_defaultColor = viewData.dataViz_histogram_defaultColor;
+        this.layoutDoc.dataViz_pie_sliceColors = Field.Copy(viewData.dataViz_pie_sliceColors);
         Object.keys(this.layoutDoc).forEach(key => {
             if (key.startsWith('dataViz_histogram_title') || key.startsWith('dataViz_lineChart_title') || key.startsWith('dataViz_pieChart_title')) {
-                this.layoutDoc['_' + key] = data[key];
+                this.layoutDoc['_' + key] = viewData[key];
             }
         });
         return true;
@@ -354,7 +347,9 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
 
     componentDidMount() {
         this._props.setContentViewBox?.(this);
-        if (!this._urlError) { if (!DataVizBox.dataset.has(CsvCast(this.dataDoc[this.fieldKey]).url.href)) this.fetchData() };
+        if (!this._urlError) {
+            if (!DataVizBox.dataset.has(CsvCast(this.dataDoc[this.fieldKey]).url.href)) this.fetchData();
+        }
         this._disposers.datavis = reaction(
             () => {
                 if (this.layoutDoc.dataViz_schemaLive === undefined) this.layoutDoc.dataViz_schemaLive = true;
@@ -516,14 +511,14 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         DocCreatorMenu.Instance.toggleDisplay(x, y);
         DocCreatorMenu.Instance.setDataViz(this);
         DocCreatorMenu.Instance.setTemplateDocs(this.getPossibleTemplates());
-    }
+    };
 
-    specificContextMenu = (x: number, y: number): void => {
+    specificContextMenu = (e: MouseEventHandler) => {
         const cm = ContextMenu.Instance;
         const options = cm.findByDescription('Options...');
         const optionItems = options?.subitems ?? [];
         optionItems.push({ description: `Analyze with AI`, event: () => this.askGPT(), icon: 'lightbulb' });
-        optionItems.push({ description: `Create documents`, event: () => this.openDocCreatorMenu(x, y), icon: 'table-cells' });
+        optionItems.push({ description: `Create documents`, event: () => this.openDocCreatorMenu(e.pageX, e.pageY), icon: 'table-cells' });
         !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' });
     };
 
@@ -533,19 +528,19 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         GPTPopup.Instance.createFilteredDoc = this.createFilteredDoc;
         GPTPopup.Instance.setDataJson('');
         GPTPopup.Instance.setMode(GPTPopupMode.DATA);
-        const data = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey]).url.href);
-        GPTPopup.Instance.setDataJson(JSON.stringify(data));
+        const csvdata = DataVizBox.dataset.get(CsvCast(this.dataDoc[this.fieldKey]).url.href);
+        GPTPopup.Instance.setDataJson(JSON.stringify(csvdata));
         GPTPopup.Instance.generateDataAnalysis();
     });
 
     getColSummary = (): string => {
-        let possibleIds: number[] = this.records.map((_, index) => index);
+        const possibleIds: number[] = this.records.map((_, index) => index);
 
         for (let i = possibleIds.length - 1; i > 0; i--) {
             const j = Math.floor(Math.random() * (i + 1));
             [possibleIds[i], possibleIds[j]] = [possibleIds[j], possibleIds[i]];
         }
-    
+
         const rowsToCheck = possibleIds.slice(0, Math.min(10, this.records.length));
 
         let prompt: string = 'Col titles: ';
@@ -553,37 +548,37 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         const cols = Array.from(Object.keys(this.records[0])).filter(header => header !== '' && header !== undefined);
 
         cols.forEach((col, i) => {
-            prompt += `Col #${i}: ${col} ------`
-        })
+            prompt += `Col #${i}: ${col} ------`;
+        });
 
-        prompt += '----------- Rows: '
+        prompt += '----------- Rows: ';
 
-        rowsToCheck.forEach((row, i) => {
-            prompt += `Row #${row}: `
+        rowsToCheck.forEach(row => {
+            prompt += `Row #${row}: `;
             cols.forEach(col => {
-                prompt += `${col}: ${this.records[row][col]} -----`
-            })
-        })
+                prompt += `${col}: ${this.records[row][col]} -----`;
+            });
+        });
 
         return prompt;
-    }
+    };
 
     updateColDefaults = () => {
-        let possibleIds: number[] = this.records.map((_, index) => index);
+        const possibleIds: number[] = this.records.map((_, index) => index);
 
         for (let i = possibleIds.length - 1; i > 0; i--) {
             const j = Math.floor(Math.random() * (i + 1));
             [possibleIds[i], possibleIds[j]] = [possibleIds[j], possibleIds[i]];
         }
-    
+
         const rowToCheck = possibleIds[0];
 
         const cols = Array.from(Object.keys(this.records[0])).filter(header => header !== '' && header !== undefined);
 
-        cols.forEach(col => { 
-            this.setColumnDefault(col, `${this.records[rowToCheck][col]}`) 
+        cols.forEach(col => {
+            this.setColumnDefault(col, `${this.records[rowToCheck][col]}`);
         });
-    }
+    };
 
     updateGPTSummary = async () => {
         this._GPTLoading = true;
@@ -594,15 +589,12 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
 
         const cols = Array.from(Object.keys(this.records[0])).filter(header => header !== '' && header !== undefined);
         cols.forEach(col => {
-            if (!this.colsInfo.get(col)) this.colsInfo.set(col, {title: col, desc: '', sizes: [], type: TemplateFieldType.UNSET});
+            if (!this.colsInfo.get(col)) this.colsInfo.set(col, { title: col, desc: '', sizes: [], type: TemplateFieldType.UNSET });
         });
 
         try {
-            const [res1, res2] = await Promise.all([
-                gptAPICall(prompt, GPTCallType.VIZSUM),
-                gptAPICall('Info:' + prompt, GPTCallType.VIZSUM2)
-            ]);
-        
+            const [res1, res2] = await Promise.all([gptAPICall(prompt, GPTCallType.VIZSUM), gptAPICall('Info:' + prompt, GPTCallType.VIZSUM2)]);
+
             if (res1) {
                 this.GPTSummary = new ObservableMap();
                 const descs: { [col: string]: string } = JSON.parse(res1);
@@ -611,10 +603,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                     if (!this.colsInfo.get(key)?.desc) this.setColumnDesc(key, val);
                 }
             }
-        
+
             if (res2) {
                 !this.GPTSummary && (this.GPTSummary = new ObservableMap());
-                const info: { [col: string]: { type: TemplateFieldType, size: TemplateFieldSize } } = JSON.parse(res2);
+                const info: { [col: string]: { type: TemplateFieldType; size: TemplateFieldSize } } = JSON.parse(res2);
                 for (const [key, val] of Object.entries(info)) {
                     const colSummary = this.GPTSummary.get(key);
                     if (colSummary) {
@@ -628,30 +620,29 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         } catch (err) {
             console.error(err);
         }
-        
-    }
+    };
 
     getPossibleTemplates = (): Doc[] => {
         const linkedDocs: Doc[] = LinkManager.Instance.getAllRelatedLinks(this.Document).map(d => DocCast(LinkManager.getOppositeAnchor(d, this.Document)));
         const linkedCollections: Doc[] = linkedDocs.filter(doc => doc.type === 'config').map(doc => DocCast(doc.annotationOn));
         const isColumnTitle = (title: string): boolean => {
             const colTitles: string[] = Object.keys(this.records[0]);
-            for (let i = 0; i < colTitles.length; ++i){
+            for (let i = 0; i < colTitles.length; ++i) {
                 if (colTitles[i] === title) {
                     return true;
                 }
             }
             return false;
-        }
+        };
         const isValidTemplate = (collection: Doc) => {
             const childDocs = DocListCast(collection[Doc.LayoutFieldKey(collection)]);
-            for (let i = 0; i < childDocs.length; ++i){
+            for (let i = 0; i < childDocs.length; ++i) {
                 if (isColumnTitle(String(childDocs[i].title))) return true;
             }
             return false;
-        }
+        };
         return linkedCollections.filter(col => isValidTemplate(col));
-    }
+    };
 
     ApplyTemplateTo = (templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined) => {
         if (!Doc.AreProtosEqual(target[targetKey] as Doc, templateDoc)) {
@@ -664,14 +655,14 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             }
         }
         return target;
-    }
+    };
 
     applyLayout = (templateInfo: DataVizTemplateInfo, docs: Doc[]) => {
         if (templateInfo.layout.type === LayoutType.Stacked) return;
         const columns: number = templateInfo.columns;
         const xGap: number = templateInfo.layout.xMargin;
         const yGap: number = templateInfo.layout.yMargin;
-        const repeat: number = templateInfo.layout.repeat;
+        // const repeat: number = templateInfo.layout.repeat;
         const startX: number = templateInfo.referencePos.x;
         const startY: number = templateInfo.referencePos.y;
         const templWidth = Number(templateInfo.doc._width);
@@ -682,8 +673,8 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         let curX: number = startX;
         let curY: number = startY;
 
-        while (docsChanged < docs.length){
-            while (i < columns && docsChanged < docs.length){ 
+        while (docsChanged < docs.length) {
+            while (i < columns && docsChanged < docs.length) {
                 docs[docsChanged].x = curX;
                 docs[docsChanged].y = curY;
                 curX += templWidth + xGap;
@@ -695,27 +686,29 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
             curX = startX;
             curY += templHeight + yGap;
         }
-    }
+    };
 
     // @action addSavedLayout = (layout: DataVizTemplateLayout) => {
     //     const saved = Cast(this.layoutDoc.dataViz_savedTemplates, listSpec('RefField'));
-        
+
     // }
 
     @action
     createDocsFromTemplate = (templateInfo: DataVizTemplateInfo) => {
         if (!templateInfo.doc) return;
         const mainCollection = this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as CollectionFreeFormView;
-        const fields: string[] = Array.from(Object.keys(this.records[0])); 
+        const fields: string[] = Array.from(Object.keys(this.records[0]));
         const selectedRows = NumListCast(this.layoutDoc.dataViz_selectedRows);
         const docs: Doc[] = selectedRows.map(row => {
-            const values: String[] = [];
+            const values: string[] = [];
             fields.forEach(col => values.push(this.records[row][col]));
 
             const proto = new Doc();
             proto.author = ClientUtils.CurrentUserEmail();
-            values.forEach((val, i) => {proto[fields[i]] = val as FieldType});
-            
+            values.forEach((val, i) => {
+                proto[fields[i]] = val as FieldType;
+            });
+
             const target = Doc.MakeDelegate(proto);
             const targetKey = StrCast(templateInfo.doc!.layout_fieldKey, 'layout');
             const applied = this.ApplyTemplateTo(templateInfo.doc!, target, targetKey, templateInfo.doc!.title + `${row}`);
@@ -728,7 +721,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         docs.forEach(doc => mainCollection.addDocument(doc));
 
         this.applyLayout(templateInfo, docs);
-    }
+    };
 
     /**
      * creates a new dataviz document filter from this one
@@ -783,7 +776,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                     transform: `scale(${scale})`,
                     position: 'absolute',
                 }}
-                onContextMenu={(e) => this.specificContextMenu(e.pageX, e.pageY)}
+                onContextMenu={this.specificContextMenu}
                 onWheel={e => e.stopPropagation()}
                 ref={this._mainCont}>
                 <div className="datatype-button">
diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx
index 0b94ae4f7..9769ecb3d 100644
--- a/src/client/views/nodes/DocumentIcon.tsx
+++ b/src/client/views/nodes/DocumentIcon.tsx
@@ -1,5 +1,5 @@
 import { Tooltip } from '@mui/material';
-import { action, makeObservable, observable } from 'mobx';
+import { makeObservable, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { factory } from 'typescript';
@@ -18,14 +18,14 @@ interface DocumentIconProps {
 @observer
 export class DocumentIcon extends ObservableReactComponent<DocumentIconProps> {
     @observable _hovered = false;
-    constructor(props: any) {
+    constructor(props: DocumentIconProps) {
         super(props);
         makeObservable(this);
     }
 
     render() {
         const { view } = this._props;
-        const { left, top, right, bottom } = view.getBounds || { left: 0, top: 0, right: 0, bottom: 0 };
+        const { left, top, bottom } = view.getBounds || { left: 0, top: 0, right: 0, bottom: 0 };
 
         return (
             <div
@@ -34,7 +34,7 @@ export class DocumentIcon extends ObservableReactComponent<DocumentIconProps> {
                     pointerEvents: 'all',
                     position: 'absolute',
                     background: SnappingManager.userBackgroundColor,
-                    transform: `translate(${left}px, ${bottom - (bottom - top)/2}px)`, //**!** 
+                    transform: `translate(${left}px, ${bottom - (bottom - top) / 2}px)`, //**!**
                 }}>
                 <Tooltip title={<div>{StrCast(this._props.view.Document?.title)}</div>}>
                     <p>d{this._props.index}</p>
@@ -44,7 +44,7 @@ export class DocumentIcon extends ObservableReactComponent<DocumentIconProps> {
     }
 }
 
-@observer   
+@observer
 export class DocumentIconContainer extends React.Component {
     public static getTransformer(): Transformer {
         const usedDocuments = new Set<number>();
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index ba85bfb68..741d63909 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -138,7 +138,7 @@ export class FieldView extends React.Component<FieldViewProps> {
         const field = this.fieldval;
         // prettier-ignore
         if (field instanceof Doc)  return <p> <b>{field.title?.toString()}</b></p>;
-        if (field === undefined) return <p>{''}</p>;
+        if (field === undefined) return <p />;
         if (field instanceof DateField) return <p>{field.date.toLocaleString()}</p>;
         if (field instanceof List) return <div> {field.map(f => Field.toString(f)).join(', ')} </div>;
         if (field instanceof WebField) return <p>{Field.toString(field.url.href)}</p>;
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index cfcf76b12..8974cccaf 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -2,7 +2,7 @@ import { Property } from 'csstype';
 import { action, computed, makeObservable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-//import * as textfit from 'textfit';
+import * as textfit from 'textfit';
 import { Field, FieldType } from '../../../fields/Doc';
 import { BoolCast, NumCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
@@ -96,7 +96,7 @@ export class LabelBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 this._timeout = setTimeout(() => this.fitTextToBox(r));
                 return textfitParams;
             }
-            //textfit(r, textfitParams);
+            textfit(r, textfitParams);
         }
         return textfitParams;
     };
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index c1367aa0b..0d7914a82 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1498,7 +1498,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
             pdfAnchorId && this.addPdfReference(pdfAnchorId);
         }
         if (this._props.autoFocus) setTimeout(() => this._editorView!.focus()); // not sure why setTimeout is needed but editing dashFieldView's doesn't work without it.
-
     }
 
     // add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet.
@@ -2087,7 +2086,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
                 </div>
             </div>
         );
-    
     }
 }
 
-- 
cgit v1.2.3-70-g09d2

