From 85c09a9e5df77ad00f3e00a2fb1e0f2e3449f97d Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 12 Dec 2023 14:39:09 -0500
Subject: cleaned up SelectionManager. fixed schema view

---
 .../collectionSchema/CollectionSchemaView.tsx      | 116 ++++++++++++---------
 1 file changed, 66 insertions(+), 50 deletions(-)

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

diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 9a00595f9..276415d56 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -1,13 +1,13 @@
 import * as React from 'react';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, ObservableMap, observe } from 'mobx';
+import { action, computed, makeObservable, observable, ObservableMap, observe, override } from 'mobx';
 import { observer } from 'mobx-react';
 import { Doc, DocListCast, Field, NumListCast, Opt, StrListCast } from '../../../../fields/Doc';
 import { Id } from '../../../../fields/FieldSymbols';
 import { List } from '../../../../fields/List';
 import { listSpec } from '../../../../fields/Schema';
 import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types';
-import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils';
+import { copyProps, emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils';
 import { Docs, DocumentOptions, DocUtils, FInfo } from '../../../documents/Documents';
 import { DocumentManager } from '../../../util/DocumentManager';
 import { DragManager } from '../../../util/DragManager';
@@ -19,7 +19,7 @@ import { Colors } from '../../global/globalEnums';
 import { DocFocusOptions, DocumentView, DocumentViewProps } from '../../nodes/DocumentView';
 import { KeyValueBox } from '../../nodes/KeyValueBox';
 import { DefaultStyleProvider, StyleProp } from '../../StyleProvider';
-import { CollectionSubView } from '../CollectionSubView';
+import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView';
 import './CollectionSchemaView.scss';
 import { SchemaColumnHeader } from './SchemaColumnHeader';
 import { SchemaRowBox } from './SchemaRowBox';
@@ -79,15 +79,27 @@ export class CollectionSchemaView extends CollectionSubView() {
     @observable _filterSearchValue: string = '';
     @observable _selectedCell: [Doc, number] | undefined = undefined;
 
+    _prevProps: SubCollectionViewProps;
+    @override _props: SubCollectionViewProps;
+    constructor(props: SubCollectionViewProps) {
+        super(props);
+        this._props = this._prevProps = props;
+        makeObservable(this);
+    }
+
+    componentDidUpdate() {
+        copyProps(this);
+    }
+
     // target HTMLelement portal for showing a popup menu to edit cell values.
     public get MenuTarget() {
         return this._menuTarget.current;
     }
 
     @computed get _selectedDocs() {
-        const selected = SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.Document));
+        const selected = SelectionManager.Docs.filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.Document));
         if (!selected.length) {
-            for (const sel of SelectionManager.Docs()) {
+            for (const sel of SelectionManager.Docs) {
                 const contextPath = DocumentManager.GetContextPath(sel, true);
                 if (contextPath.includes(this.Document)) {
                     const parentInd = contextPath.indexOf(this.Document);
@@ -107,7 +119,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     }
 
     @computed get tableWidth() {
-        return this.props.PanelWidth() - this.previewWidth - (this.previewWidth === 0 ? 0 : CollectionSchemaView._previewDividerWidth);
+        return this._props.PanelWidth() - this.previewWidth - (this.previewWidth === 0 ? 0 : CollectionSchemaView._previewDividerWidth);
     }
 
     @computed get columnKeys() {
@@ -139,9 +151,8 @@ export class CollectionSchemaView extends CollectionSubView() {
         return BoolCast(this.layoutDoc.sortDesc);
     }
 
-    @action
     componentDidMount() {
-        this.props.setContentView?.(this);
+        this._props.setContentView?.(this);
         document.addEventListener('keydown', this.onKeyDown);
 
         Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => this.fieldInfos.set(pair[0], pair[1]));
@@ -239,7 +250,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     @undoBatch
-    @action
     setColumnSort = (field: string | undefined, desc: boolean = false) => {
         this.layoutDoc.sortField = field;
         this.layoutDoc.sortDesc = desc;
@@ -248,7 +258,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     addRow = (doc: Doc | Doc[]) => this.addDocument(doc);
 
     @undoBatch
-    @action
     changeColumnKey = (index: number, newKey: string, defaultVal?: any) => {
         if (!this.documentKeys.includes(newKey)) {
             this.addNewKey(newKey, defaultVal);
@@ -260,7 +269,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     @undoBatch
-    @action
     addColumn = (key: string, defaultVal?: any) => {
         if (!this.documentKeys.includes(key)) {
             this.addNewKey(key, defaultVal);
@@ -281,7 +289,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     addNewKey = (key: string, defaultVal: any) => this.childDocs.forEach(doc => (doc[key] = defaultVal));
 
     @undoBatch
-    @action
     removeColumn = (index: number) => {
         if (this.columnKeys.length === 1) return;
         const currWidths = this.storedColumnWidths.slice();
@@ -320,8 +327,8 @@ export class CollectionSchemaView extends CollectionSubView() {
                 change = this._displayColumnWidths[shrinking] - CollectionSchemaView._minColWidth;
             }
 
-            this._displayColumnWidths[shrinking] -= change * this.props.ScreenToLocalTransform().Scale;
-            this._displayColumnWidths[growing] += change * this.props.ScreenToLocalTransform().Scale;
+            this._displayColumnWidths[shrinking] -= change * this._props.ScreenToLocalTransform().Scale;
+            this._displayColumnWidths[growing] += change * this._props.ScreenToLocalTransform().Scale;
 
             return false;
         }
@@ -335,7 +342,6 @@ export class CollectionSchemaView extends CollectionSubView() {
     };
 
     @undoBatch
-    @action
     moveColumn = (fromIndex: number, toIndex: number) => {
         let currKeys = this.columnKeys.slice();
         currKeys.splice(toIndex, 0, currKeys.splice(fromIndex, 1)[0]);
@@ -379,7 +385,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     @action
     highlightDropColumn = (e: PointerEvent) => {
         e.stopPropagation();
-        const mouseX = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0];
+        const mouseX = this._props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0];
         const index = this.findDropIndex(mouseX);
         this._colEles.forEach((colRef, i) => {
             let leftStyle = '';
@@ -439,7 +445,7 @@ export class CollectionSchemaView extends CollectionSubView() {
 
     onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
         if (de.complete.columnDragData) {
-            const mouseX = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y)[0];
+            const mouseX = this._props.ScreenToLocalTransform().transformPoint(de.x, de.y)[0];
             const index = this.findDropIndex(mouseX);
             this.moveColumn(de.complete.columnDragData.colIndex, index ?? de.complete.columnDragData.colIndex);
 
@@ -483,7 +489,7 @@ export class CollectionSchemaView extends CollectionSubView() {
         const nativeWidth = this._previewRef!.getBoundingClientRect();
         const minWidth = 40;
         const maxWidth = 1000;
-        const movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0];
+        const movedWidth = this._props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0];
         const width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth;
         this.layoutDoc.schema_previewWidth = width;
         return false;
@@ -507,8 +513,8 @@ export class CollectionSchemaView extends CollectionSubView() {
         const found = this._tableContentRef && Array.from(this._tableContentRef.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]);
         if (found) {
             const rect = found.getBoundingClientRect();
-            const localRect = this.props.ScreenToLocalTransform().transformBounds(rect.left, rect.top, rect.width, rect.height);
-            if (localRect.y < this.rowHeightFunc() || localRect.y + localRect.height > this.props.PanelHeight()) {
+            const localRect = this._props.ScreenToLocalTransform().transformBounds(rect.left, rect.top, rect.width, rect.height);
+            if (localRect.y < this.rowHeightFunc() || localRect.y + localRect.height > this._props.PanelHeight()) {
                 let focusSpeed = options.zoomTime ?? 50;
                 smoothScroll(focusSpeed, this._tableContentRef!, localRect.y + this._tableContentRef!.scrollTop - this.rowHeightFunc(), options.easeFunc);
                 return focusSpeed;
@@ -755,7 +761,7 @@ export class CollectionSchemaView extends CollectionSubView() {
     @computed get renderFilterOptions() {
         const keyOptions: string[] = [];
         const columnKey = this.columnKeys[this._filterColumnIndex!];
-        const allDocs = DocListCast(this.dataDoc[this.props.fieldKey]);
+        const allDocs = DocListCast(this.dataDoc[this._props.fieldKey]);
         allDocs.forEach(doc => {
             const value = StrCast(doc[columnKey]);
             if (!keyOptions.includes(value) && value !== '' && (this._filterSearchValue === '' || value.includes(this._filterSearchValue))) {
@@ -779,9 +785,9 @@ export class CollectionSchemaView extends CollectionSubView() {
                         onClick={e => e.stopPropagation()}
                         onChange={action(e => {
                             if (e.target.checked) {
-                                Doc.setDocFilter(this.props.Document, columnKey, key, 'check');
+                                Doc.setDocFilter(this.Document, columnKey, key, 'check');
                             } else {
-                                Doc.setDocFilter(this.props.Document, columnKey, key, 'remove');
+                                Doc.setDocFilter(this.Document, columnKey, key, 'remove');
                             }
                         })}
                         checked={bool}
@@ -828,8 +834,8 @@ export class CollectionSchemaView extends CollectionSubView() {
     }
     rowHeightFunc = () => (BoolCast(this.layoutDoc._schema_singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight);
     sortedDocsFunc = () => this.sortedDocs;
-    isContentActive = () => this.props.isSelected() || this.props.isContentActive();
-    screenToLocal = () => this.props.ScreenToLocalTransform().translate(-this.tableWidth, 0);
+    isContentActive = () => this._props.isSelected() || this._props.isContentActive();
+    screenToLocal = () => this._props.ScreenToLocalTransform().translate(-this.tableWidth, 0);
     previewWidthFunc = () => this.previewWidth;
     render() {
         return (
@@ -838,7 +844,7 @@ export class CollectionSchemaView extends CollectionSubView() {
                 <div
                     className="schema-table"
                     style={{ width: `calc(100% - ${this.previewWidth}px)` }}
-                    onWheel={e => this.props.isContentActive() && e.stopPropagation()}
+                    onWheel={e => this._props.isContentActive() && e.stopPropagation()}
                     ref={r => {
                         // prevent wheel events from passively propagating up through containers
                         r?.addEventListener('wheel', (e: WheelEvent) => {}, { passive: false });
@@ -864,7 +870,7 @@ export class CollectionSchemaView extends CollectionSubView() {
                                 openContextMenu={this.openContextMenu}
                                 dragColumn={this.dragColumn}
                                 setColRef={this.setColRef}
-                                isContentActive={this.props.isContentActive}
+                                isContentActive={this._props.isContentActive}
                             />
                         ))}
                     </div>
@@ -895,10 +901,10 @@ export class CollectionSchemaView extends CollectionSubView() {
                                 onClickScriptDisable="always"
                                 focus={emptyFunction}
                                 defaultDoubleClick={returnIgnore}
-                                renderDepth={this.props.renderDepth + 1}
+                                renderDepth={this._props.renderDepth + 1}
                                 rootSelected={this.rootSelected}
                                 PanelWidth={this.previewWidthFunc}
-                                PanelHeight={this.props.PanelHeight}
+                                PanelHeight={this._props.PanelHeight}
                                 isContentActive={returnTrue}
                                 isDocumentActive={returnFalse}
                                 ScreenToLocalTransform={this.screenToLocal}
@@ -907,12 +913,12 @@ export class CollectionSchemaView extends CollectionSubView() {
                                 searchFilterDocs={this.searchFilterDocs}
                                 styleProvider={DefaultStyleProvider}
                                 docViewPath={returnEmptyDoclist}
-                                moveDocument={this.props.moveDocument}
+                                moveDocument={this._props.moveDocument}
                                 addDocument={this.addRow}
-                                removeDocument={this.props.removeDocument}
+                                removeDocument={this._props.removeDocument}
                                 whenChildContentsActiveChanged={returnFalse}
-                                addDocTab={this.props.addDocTab}
-                                pinToPres={this.props.pinToPres}
+                                addDocTab={this._props.addDocTab}
+                                pinToPres={this._props.pinToPres}
                                 bringToFront={returnFalse}
                             />
                         )}
@@ -936,7 +942,7 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP
         return (
             <div className="schema-table-content" ref={this.props.setRef} style={{ height: `calc(100% - ${CollectionSchemaView._newNodeInputHeight + this.props.rowHeight()}px)` }}>
                 {this.props.childDocs().docs.map((doc: Doc, index: number) => (
-                    <div className="schema-row-wrapper" style={{ height: this.props.rowHeight() }}>
+                    <div key={doc[Id]} className="schema-row-wrapper" style={{ height: this.props.rowHeight() }}>
                         <CollectionSchemaViewDoc doc={doc} schema={this.props.schema} index={index} rowHeight={this.props.rowHeight} />
                     </div>
                 ))}
@@ -954,8 +960,18 @@ interface CollectionSchemaViewDocProps {
 
 @observer
 class CollectionSchemaViewDoc extends React.Component<CollectionSchemaViewDocProps> {
-    tableWidthFunc = () => this.props.schema.tableWidth;
-    screenToLocalXf = () => this.props.schema.props.ScreenToLocalTransform().translate(0, -this.props.rowHeight() - this.props.index * this.props.rowHeight());
+    _prevProps: CollectionSchemaViewDocProps;
+    @observable _props;
+    constructor(props: CollectionSchemaViewDocProps) {
+        super(props);
+        this._props = this._prevProps = props;
+        makeObservable(this);
+    }
+    componentDidUpdate() {
+        copyProps(this);
+    }
+    tableWidthFunc = () => this._props.schema.tableWidth;
+    screenToLocalXf = () => this._props.schema._props.ScreenToLocalTransform().translate(0, -this._props.rowHeight() - this._props.index * this._props.rowHeight());
     noOpacityStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => {
         if (property === StyleProp.Opacity) return 1;
         return DefaultStyleProvider(doc, props, property);
@@ -963,30 +979,30 @@ class CollectionSchemaViewDoc extends React.Component<CollectionSchemaViewDocPro
     render() {
         return (
             <DocumentView
-                key={this.props.doc[Id]}
-                {...this.props.schema.props}
-                LayoutTemplate={this.props.schema.props.childLayoutTemplate}
-                LayoutTemplateString={SchemaRowBox.LayoutString(this.props.schema.props.fieldKey, this.props.index)}
-                Document={this.props.doc}
-                renderDepth={this.props.schema.props.renderDepth + 1}
+                key={this._props.doc[Id]}
+                {...this._props.schema._props}
+                LayoutTemplate={this._props.schema._props.childLayoutTemplate}
+                LayoutTemplateString={SchemaRowBox.LayoutString(this._props.schema._props.fieldKey, this._props.index)}
+                Document={this._props.doc}
+                renderDepth={this._props.schema._props.renderDepth + 1}
                 PanelWidth={this.tableWidthFunc}
-                PanelHeight={this.props.rowHeight}
+                PanelHeight={this._props.rowHeight}
                 styleProvider={this.noOpacityStyleProvider}
                 waitForDoubleClickToClick={returnNever}
                 defaultDoubleClick={returnIgnore}
                 dragAction="move"
                 onClickScriptDisable="always"
-                focus={this.props.schema.focusDocument}
-                childFilters={this.props.schema.childDocFilters}
-                childFiltersByRanges={this.props.schema.childDocRangeFilters}
-                searchFilterDocs={this.props.schema.searchFilterDocs}
-                rootSelected={this.props.schema.rootSelected}
+                focus={this._props.schema.focusDocument}
+                childFilters={this._props.schema.childDocFilters}
+                childFiltersByRanges={this._props.schema.childDocRangeFilters}
+                searchFilterDocs={this._props.schema.searchFilterDocs}
+                rootSelected={this._props.schema.rootSelected}
                 ScreenToLocalTransform={this.screenToLocalXf}
                 bringToFront={emptyFunction}
                 dragWhenActive={true}
-                isDocumentActive={this.props.schema.props.childDocumentsActive?.() ? this.props.schema.props.isDocumentActive : this.props.schema.isContentActive}
+                isDocumentActive={this._props.schema._props.childDocumentsActive?.() ? this._props.schema._props.isDocumentActive : this._props.schema.isContentActive}
                 isContentActive={emptyFunction}
-                whenChildContentsActiveChanged={this.props.schema.props.whenChildContentsActiveChanged}
+                whenChildContentsActiveChanged={this._props.schema._props.whenChildContentsActiveChanged}
                 hideDecorations={true}
                 hideTitle={true}
                 hideDocumentButtonBar={true}
-- 
cgit v1.2.3-70-g09d2

