From 0ed7131587c6739483da64a93d9f2ab6fdfbc15a Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 25 Aug 2022 11:06:38 -0400
Subject: fixed crashes in notetaking view and cleaned up code a bit.  fixed
 undo of column deletion.

---
 .../views/collections/CollectionNoteTakingView.tsx | 103 ++++++++-------------
 1 file changed, 41 insertions(+), 62 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index b359ef420..5a6d899ef 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -11,7 +11,7 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Ty
 import { TraceMobx } from '../../../fields/util';
 import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, returnZero, smoothScroll, Utils } from '../../../Utils';
 import { Docs, DocUtils } from '../../documents/Documents';
-import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
+import { DocumentType } from '../../documents/DocumentTypes';
 import { DragManager, dropActionType } from '../../util/DragManager';
 import { SnappingManager } from '../../util/SnappingManager';
 import { Transform } from '../../util/Transform';
@@ -19,7 +19,6 @@ import { undoBatch } from '../../util/UndoManager';
 import { ContextMenu } from '../ContextMenu';
 import { ContextMenuProps } from '../ContextMenuItem';
 import { LightboxView } from '../LightboxView';
-import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView';
 import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment } from '../nodes/DocumentView';
 import { FieldViewProps } from '../nodes/FieldView';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
@@ -30,13 +29,6 @@ import { CollectionNoteTakingViewDivider } from './CollectionNoteTakingViewDivid
 import { CollectionSubView } from './CollectionSubView';
 const _global = (window /* browser */ || global) /* node */ as any;
 
-export type collectionNoteTakingViewProps = {
-    chromeHidden?: boolean;
-    viewType?: CollectionViewType;
-    NativeWidth?: () => number;
-    NativeHeight?: () => number;
-};
-
 /**
  * CollectionNoteTakingView is a column-based view for displaying documents. In this view, the user can (1)
  * add and remove columns (2) change column sizes and (3) move documents within and between columns. This
@@ -45,28 +37,32 @@ export type collectionNoteTakingViewProps = {
  * the rest of Dash, so it may be worthwhile to transition the headers to simple documents.
  */
 @observer
-export class CollectionNoteTakingView extends CollectionSubView<Partial<collectionNoteTakingViewProps>>() {
+export class CollectionNoteTakingView extends CollectionSubView() {
     _disposers: { [key: string]: IReactionDisposer } = {};
     _masonryGridRef: HTMLDivElement | null = null;
     _draggerRef = React.createRef<HTMLDivElement>();
+    notetakingCategoryField = 'NotetakingCategory';
+    dividerWidth = 16;
     @observable docsDraggedRowCol: number[] = [];
     @observable _cursor: CursorProperty = 'grab';
     @observable _scroll = 0;
     @computed get chromeHidden() {
-        return this.props.chromeHidden || BoolCast(this.layoutDoc.chromeHidden);
+        return BoolCast(this.layoutDoc.chromeHidden);
     }
     // columnHeaders returns the list of SchemaHeaderFields currently being used by the layout doc to render the columns
     @computed get columnHeaders() {
         const columnHeaders = Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null);
-        const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders.find(sh => sh.heading === 'unset'));
+        const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset'));
         if (needsUnsetCategory) {
-            setTimeout(() => columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1)));
+            setTimeout(() => {
+                const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset'));
+                if (needsUnsetCategory) {
+                    if (columnHeaders) columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1));
+                    else this.dataDoc.columnHeaders = new List<SchemaHeaderField>();
+                }
+            });
         }
-        return columnHeaders;
-    }
-    // notetakingCategoryField returns the key to accessing a document's column value
-    @computed get notetakingCategoryField() {
-        return 'NotetakingCategory';
+        return columnHeaders ?? ([] as SchemaHeaderField[]);
     }
     @computed get headerMargin() {
         return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin);
@@ -74,10 +70,6 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     @computed get xMargin() {
         return NumCast(this.layoutDoc._xMargin, 2 * Math.min(this.gridGap, 0.05 * this.props.PanelWidth()));
     }
-    // dividerWidth returns the width of a CollectionNoteTakingViewDivider
-    @computed get dividerWidth() {
-        return 32;
-    }
     @computed get yMargin() {
         return this.props.yPadding || NumCast(this.layoutDoc._yMargin, 5);
     }
@@ -99,19 +91,10 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     // availableWidth is the total amount of non-divider width. Since widths are stored relatively,
     // we use availableWidth to convert from a percentage to a pixel count.
     @computed get availableWidth() {
-        const numDividers = this.columnHeaders.length - 1;
+        const numDividers = this.numGroupColumns - 1;
         return this.maxColWidth - numDividers * this.dividerWidth;
     }
 
-    // Documents should NOT have column category fields until entering this view, so the contructor creates the 'New Column'
-    // category for the user to then edit later.
-    constructor(props: any) {
-        super(props);
-        if (this.columnHeaders === undefined) {
-            this.dataDoc.columnHeaders = new List<SchemaHeaderField>([new SchemaHeaderField('New Column', undefined, undefined, 1)]);
-        }
-    }
-
     // children is passed as a prop to the NoteTakingField, which uses this function
     // to render the docs you see within an individual column.
     children = (docs: Doc[]) => {
@@ -149,7 +132,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
             }
         });
         // now we add back in the docs that we're dragging
-        if (rowCol.length) {
+        if (rowCol.length && columnHeaders.length > rowCol[1]) {
             const offset = 0;
             sections.get(columnHeaders[rowCol[1]])?.splice(rowCol[0] - offset, 0, ...DragManager.docsBeingDragged);
         }
@@ -236,9 +219,6 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
             if (this.props.childOpacity) {
                 return this.props.childOpacity();
             }
-            if (this.Document._currentFrame !== undefined) {
-                return CollectionFreeFormDocumentView.getValues(doc, NumCast(this.Document._currentFrame))?.opacity;
-            }
         }
         return this.props.styleProvider?.(doc, props, property);
     };
@@ -392,17 +372,19 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
             });
             // we alter the pivot fields of the docs in case they are moved to a new column.
             const colIndex = this.getColumnFromXCoord(xCoord);
-            const colHeader = StrCast(this.columnHeaders[colIndex].heading);
+            const colHeader = colIndex === undefined ? 'unset' : StrCast(this.columnHeaders[colIndex].heading);
             DragManager.docsBeingDragged.forEach(d => (d[this.notetakingCategoryField] = colHeader));
             // used to notify sections to re-render
             this.docsDraggedRowCol.length = 0;
-            this.docsDraggedRowCol.push(dropInd, this.getColumnFromXCoord(xCoord));
+            const columnFromCoord = this.getColumnFromXCoord(xCoord);
+            columnFromCoord !== undefined && this.docsDraggedRowCol.push(dropInd, columnFromCoord);
         }
     };
 
     // getColumnFromXCoord returns the column index for a given x-coordinate (currently always the client's mouse coordinate).
     // This function is used to know which document a column SHOULD be in while it is being dragged.
-    getColumnFromXCoord = (xCoord: number): number => {
+    getColumnFromXCoord = (xCoord: number): number | undefined => {
+        let colIndex: number | undefined = undefined;
         const numColumns = this.columnHeaders.length;
         const coords = [];
         let colStartXCoord = 0;
@@ -411,7 +393,6 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
             colStartXCoord += this.columnHeaders[i].width * this.availableWidth + this.dividerWidth;
         }
         coords.push(this.PanelWidth);
-        let colIndex = 0;
         for (let i = 0; i < numColumns; i++) {
             if (xCoord > coords[i] && xCoord < coords[i + 1]) {
                 colIndex = i;
@@ -423,20 +404,16 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
 
     // getDocsFromXCoord returns the docs of a column based on the x-coordinate provided.
     getDocsFromXCoord = (xCoord: number): Doc[] => {
-        const colIndex = this.getColumnFromXCoord(xCoord);
-        const colHeader = StrCast(this.columnHeaders[colIndex].heading);
-        // const docs = this.childDocList
-        const docs = this.childDocs;
         const docsMatchingHeader: Doc[] = [];
-        if (docs) {
-            docs.map(d => {
-                if (d instanceof Promise) return;
-                const sectionValue = (d[this.notetakingCategoryField] as object) ?? 'unset';
-                if (sectionValue.toString() == colHeader) {
-                    docsMatchingHeader.push(d);
-                }
-            });
-        }
+        const colIndex = this.getColumnFromXCoord(xCoord);
+        const colHeader = colIndex === undefined ? 'unset' : StrCast(this.columnHeaders[colIndex].heading);
+        this.childDocs?.map(d => {
+            if (d instanceof Promise) return;
+            const sectionValue = (d[this.notetakingCategoryField] as object) ?? 'unset';
+            if (sectionValue.toString() == colHeader) {
+                docsMatchingHeader.push(d);
+            }
+        });
         return docsMatchingHeader;
     };
 
@@ -511,7 +488,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
                     this.onPointerMove(true, e.clientX, e.clientY);
                     docus?.map((doc: Doc) => this.addDocument(doc));
                     const newDoc = this.childDocs.lastElement();
-                    const colHeader = StrCast(this.columnHeaders[colInd].heading);
+                    const colHeader = colInd === undefined ? 'unset' : StrCast(this.columnHeaders[colInd].heading);
                     newDoc[this.notetakingCategoryField] = colHeader;
                     const docs = this.childDocList;
                     if (docs && targInd !== -1) {
@@ -570,9 +547,9 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
                 maxColWidth={this.maxColWidth}
                 availableWidth={this.availableWidth}
                 PanelWidth={this.PanelWidth}
-                key={heading?.heading ?? ''}
+                key={heading?.heading ?? 'unset'}
                 headings={this.headings}
-                heading={heading?.heading ?? ''}
+                heading={heading?.heading ?? 'unset'}
                 headingObject={heading}
                 docList={docList}
                 yMargin={this.yMargin}
@@ -589,10 +566,12 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     @undoBatch
     @action
     addGroup = (value: string) => {
-        for (const header of this.columnHeaders) {
-            if (header.heading == value) {
-                alert('You cannot use an existing column name. Please try a new column name');
-                return value;
+        if (this.columnHeaders) {
+            for (const header of this.columnHeaders) {
+                if (header.heading == value) {
+                    alert('You cannot use an existing column name. Please try a new column name');
+                    return value;
+                }
             }
         }
         const columnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null);
@@ -678,10 +657,10 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     }
 
     @computed get nativeWidth() {
-        return this.props.NativeWidth?.() ?? Doc.NativeWidth(this.layoutDoc);
+        return Doc.NativeWidth(this.layoutDoc);
     }
     @computed get nativeHeight() {
-        return this.props.NativeHeight?.() ?? Doc.NativeHeight(this.layoutDoc);
+        return Doc.NativeHeight(this.layoutDoc);
     }
 
     @computed get scaling() {
-- 
cgit v1.2.3-70-g09d2

