From be1ac92cdc609a7931ec8427f507648da117b4ea Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 10 Apr 2024 13:53:38 -0400
Subject: fixed buttons to have an embedContainer. cleaning up notetaking view
 - fixing colors for input buttons, fixing when buttons appear (by extending
 the column targe to always be 100%)

---
 src/client/views/collections/CollectionNoteTakingView.tsx | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 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 5b91216cb..12e2cc1a8 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -9,7 +9,7 @@ import { listSpec } from '../../../fields/Schema';
 import { SchemaHeaderField } from '../../../fields/SchemaHeaderField';
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
-import { DivHeight, emptyFunction, returnZero, smoothScroll, Utils } from '../../../Utils';
+import { DivHeight, emptyFunction, lightOrDark, returnZero, smoothScroll, Utils } from '../../../Utils';
 import { Docs, DocUtils } from '../../documents/Documents';
 import { DragManager, dropActionType } from '../../util/DragManager';
 import { SnappingManager } from '../../util/SnappingManager';
@@ -26,6 +26,7 @@ import './CollectionNoteTakingView.scss';
 import { CollectionNoteTakingViewColumn } from './CollectionNoteTakingViewColumn';
 import { CollectionNoteTakingViewDivider } from './CollectionNoteTakingViewDivider';
 import { CollectionSubView } from './CollectionSubView';
+import { Colors } from '../global/globalEnums';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 /**
@@ -500,10 +501,11 @@ export class CollectionNoteTakingView extends CollectionSubView() {
     editableViewProps = () => ({
         GetValue: () => '',
         SetValue: this.addGroup,
-        contents: '+ New Column',
+        contents: '+ Column',
     });
 
     refList = () => this._refList;
+    backgroundColor = () => this._props.DocumentView?.().backgroundColor();
 
     // sectionNoteTaking returns a CollectionNoteTakingViewColumn (which is an individual column)
     sectionNoteTaking = (heading: SchemaHeaderField | undefined, docList: Doc[]) => (
@@ -511,7 +513,9 @@ export class CollectionNoteTakingView extends CollectionSubView() {
             key={heading?.heading ?? 'unset'}
             PanelWidth={this._props.PanelWidth}
             refList={this._refList}
+            backgroundColor={this.backgroundColor}
             select={this._props.select}
+            isContentActive={this.isContentActive}
             addDocument={this.addDocument}
             chromeHidden={this.chromeHidden}
             colHeaderData={this.colHeaderData}
@@ -613,12 +617,11 @@ export class CollectionNoteTakingView extends CollectionSubView() {
         TraceMobx();
         return (
             <div
-                className="collectionNoteTakingView"
+                className={`collectionNoteTakingView ${lightOrDark(this.backgroundColor()) === Colors.WHITE ? 'collectionNoteTakingViewLight' : ''}`}
                 ref={this.createRef}
-                key="notes"
                 style={{
-                    overflowY: this._props.isContentActive() ? 'auto' : 'hidden',
-                    background: this._props.styleProvider?.(this.Document, this._props, StyleProp.BackgroundColor),
+                    overflowY: this.isContentActive() ? 'auto' : 'hidden',
+                    background: this.backgroundColor(),
                     pointerEvents: this.backgroundEvents,
                 }}
                 onScroll={action(e => (this._scroll = e.currentTarget.scrollTop))}
-- 
cgit v1.2.3-70-g09d2


From ffb6621a7f822c3d605e4749b3f3be799ad1ef94 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 10 Apr 2024 14:04:25 -0400
Subject: enabled a notetaking category field other than 'NotetakingCategory'

---
 src/client/views/collections/CollectionNoteTakingView.tsx | 6 ++++--
 1 file changed, 4 insertions(+), 2 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 12e2cc1a8..5c52d2398 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -41,7 +41,9 @@ export class CollectionNoteTakingView extends CollectionSubView() {
     _disposers: { [key: string]: IReactionDisposer } = {};
     _masonryGridRef: HTMLDivElement | null = null;
     _draggerRef = React.createRef<HTMLDivElement>();
-    notetakingCategoryField = 'NotetakingCategory';
+    @computed get notetakingCategoryField() {
+        return StrCast(this.dataDoc.notetaking_category, 'NotetakingCategory');
+    }
     public DividerWidth = 16;
     @observable docsDraggedRowCol: number[] = [];
     @observable _scroll = 0;
@@ -370,7 +372,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
             // we alter the pivot fields of the docs in case they are moved to a new column.
             const colIndex = this.getColumnFromXCoord(xCoord);
             const colHeader = colIndex === undefined ? 'unset' : StrCast(this.colHeaderData[colIndex].heading);
-            DragManager.docsBeingDragged.forEach(d => (d[this.notetakingCategoryField] = colHeader));
+            DragManager.docsBeingDragged.map(doc => doc[DocData]).forEach(d => (d[this.notetakingCategoryField] = colHeader));
             // used to notify sections to re-render
             this.docsDraggedRowCol.length = 0;
             const columnFromCoord = this.getColumnFromXCoord(xCoord);
-- 
cgit v1.2.3-70-g09d2


From 53fbe74037f03456a678d592d0ae5660c2f0d55e Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 10 Apr 2024 21:02:05 -0400
Subject: more notetaking fixes - turn off autoSize, unobserve children.  fixed
 typing a new note to delete placeholder text.   added autoCreate for columns.
  added pivot column selector for notetaking view.

---
 .../collections/CollectionNoteTakingView.scss      |  9 +++
 .../views/collections/CollectionNoteTakingView.tsx | 80 +++++++++++++++++-----
 .../collections/CollectionNoteTakingViewColumn.tsx |  4 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  2 +-
 4 files changed, 73 insertions(+), 22 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.scss b/src/client/views/collections/CollectionNoteTakingView.scss
index 81000e7a5..95fda7b0a 100644
--- a/src/client/views/collections/CollectionNoteTakingView.scss
+++ b/src/client/views/collections/CollectionNoteTakingView.scss
@@ -494,6 +494,15 @@
     .rc-switch-checked .rc-switch-inner {
         left: 8px;
     }
+
+    .collectionNoteTaking-pivotField {
+        display: none;
+    }
+    &:hover {
+        .collectionNoteTaking-pivotField {
+            display: unset;
+        }
+    }
 }
 
 .collectionNoteTakingViewLight {
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 5c52d2398..d8a0aebb1 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -14,9 +14,10 @@ import { Docs, DocUtils } from '../../documents/Documents';
 import { DragManager, dropActionType } from '../../util/DragManager';
 import { SnappingManager } from '../../util/SnappingManager';
 import { Transform } from '../../util/Transform';
-import { undoBatch } from '../../util/UndoManager';
+import { undoable, undoBatch } from '../../util/UndoManager';
 import { ContextMenu } from '../ContextMenu';
 import { ContextMenuProps } from '../ContextMenuItem';
+import { Colors } from '../global/globalEnums';
 import { LightboxView } from '../LightboxView';
 import { DocumentView } from '../nodes/DocumentView';
 import { FieldViewProps, FocusViewOptions } from '../nodes/FieldView';
@@ -26,7 +27,7 @@ import './CollectionNoteTakingView.scss';
 import { CollectionNoteTakingViewColumn } from './CollectionNoteTakingViewColumn';
 import { CollectionNoteTakingViewDivider } from './CollectionNoteTakingViewDivider';
 import { CollectionSubView } from './CollectionSubView';
-import { Colors } from '../global/globalEnums';
+import { FieldsDropdown } from '../FieldsDropdown';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 /**
@@ -42,7 +43,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
     _masonryGridRef: HTMLDivElement | null = null;
     _draggerRef = React.createRef<HTMLDivElement>();
     @computed get notetakingCategoryField() {
-        return StrCast(this.dataDoc.notetaking_category, 'NotetakingCategory');
+        return StrCast(this.dataDoc.notetaking_column, StrCast(this.layoutDoc.pivotField, 'notetaking_column'));
     }
     public DividerWidth = 16;
     @observable docsDraggedRowCol: number[] = [];
@@ -155,25 +156,34 @@ export class CollectionNoteTakingView extends CollectionSubView() {
         );
     };
 
+    @computed get allFieldValues() {
+        return new Set(this.childDocs.map(doc => StrCast(doc[this.notetakingCategoryField])));
+    }
+
     componentDidMount() {
         super.componentDidMount?.();
         document.addEventListener('pointerup', this.removeDocDragHighlight, true);
-        this._disposers.layout_autoHeight = reaction(
-            () => this.layoutDoc._layout_autoHeight,
-            layout_autoHeight => layout_autoHeight && this._props.setHeight?.(this.headerMargin + Math.max(...this._refList.map(DivHeight)))
+
+        this._disposers.autoColumns = reaction(
+            () => (this.layoutDoc._notetaking_columns_autoCreate ? Array.from(this.allFieldValues) : undefined),
+            columns => undoable(() => columns?.filter(col => !this.colHeaderData.some(h => h.heading === col)).forEach(col => this.addColumn(col)), 'adding columns')(),
+            { fireImmediately: true }
         );
 
         this._disposers.refList = reaction(
             () => ({ refList: this._refList.slice(), autoHeight: this.layoutDoc._layout_autoHeight && !LightboxView.Contains(this.DocumentView?.()) }),
             ({ refList, autoHeight }) => {
-                if (autoHeight) refList.forEach(r => this.observer.observe(r));
-                else this.observer.disconnect();
+                if (autoHeight) {
+                    refList.forEach(r => this.observer.observe(r));
+                    this._props.setHeight?.(this.headerMargin + Math.max(...this._refList.map(DivHeight)));
+                } else this.observer.disconnect();
             },
             { fireImmediately: true }
         );
     }
 
     componentWillUnmount() {
+        this.observer.disconnect();
         document.removeEventListener('pointerup', this.removeDocDragHighlight, true);
         super.componentWillUnmount();
         Object.keys(this._disposers).forEach(key => this._disposers[key]());
@@ -300,7 +310,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
     getDocWidth(d: Doc) {
         const heading = !d[this.notetakingCategoryField] ? 'unset' : Field.toString(d[this.notetakingCategoryField] as Field);
         const existingHeader = this.colHeaderData.find(sh => sh.heading === heading);
-        const existingWidth = existingHeader?.width ? existingHeader.width : 0;
+        const existingWidth = this.layoutDoc._notetaking_columns_autoSize ? 1 / (this.colHeaderData.length ?? 1) : existingHeader?.width ? existingHeader.width : 0;
         const maxWidth = existingWidth > 0 ? existingWidth * this.availableWidth : this.maxColWidth;
         const width = d.layout_fitWidth ? maxWidth : NumCast(d._width);
         return Math.min(maxWidth - CollectionNoteTakingViewColumn.ColumnMargin, width < maxWidth ? width : maxWidth);
@@ -502,7 +512,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
 
     editableViewProps = () => ({
         GetValue: () => '',
-        SetValue: this.addGroup,
+        SetValue: this.addColumn,
         contents: '+ Column',
     });
 
@@ -543,18 +553,26 @@ export class CollectionNoteTakingView extends CollectionSubView() {
         />
     );
 
+    @undoBatch
+    remColumn = (value: SchemaHeaderField) => {
+        const colHdrData = Array.from(Cast(this._props.Document[this._props.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null));
+        if (value) {
+            const index = colHdrData.indexOf(value);
+            index !== -1 && colHdrData.splice(index, 1);
+            this.resizeColumns(colHdrData);
+        }
+    };
+
     // addGroup is called when adding a new columnHeader, adding a SchemaHeaderField to our list of
     // columnHeaders and resizing the existing columns to make room for our new one.
     @undoBatch
-    addGroup = (value: string) => {
-        if (this.colHeaderData) {
-            for (const header of this.colHeaderData) {
-                if (header.heading === value) {
-                    alert('You cannot use an existing column name. Please try a new column name');
-                    return value;
-                }
+    addColumn = (value: string) => {
+        this.colHeaderData.forEach(header => {
+            if (header.heading === value) {
+                alert('You cannot use an existing column name. Please try a new column name');
+                return value;
             }
-        }
+        });
         const columnHeaders = Array.from(Cast(this.dataDoc[this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null));
         const newColWidth = 1 / (this.numGroupColumns + 1);
         columnHeaders.push(new SchemaHeaderField(value, undefined, undefined, newColWidth));
@@ -562,11 +580,25 @@ export class CollectionNoteTakingView extends CollectionSubView() {
         return true;
     };
 
+    removeEmptyColumns = undoable(() => {
+        this.colHeaderData.filter(h => !this.allFieldValues.has(h.heading)).forEach(this.remColumn);
+    }, 'remove empty Columns');
+
     onContextMenu = (e: React.MouseEvent): void => {
         // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout
         if (!e.isPropagationStopped()) {
             const subItems: ContextMenuProps[] = [];
-            subItems.push({ description: `${this.layoutDoc._columnsFill ? 'Variable Size' : 'Autosize'} Column`, event: () => (this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill), icon: 'plus' });
+            subItems.push({
+                description: `${this.layoutDoc._notetaking_columns_autoCreate ? 'Manually' : 'Automatically'} Create columns`,
+                event: () => (this.layoutDoc._notetaking_columns_autoCreate = !this.layoutDoc._notetaking_columns_autoCreate),
+                icon: 'computer',
+            });
+            subItems.push({ description: 'Remove Empty Columns', event: this.removeEmptyColumns, icon: 'computer' });
+            subItems.push({
+                description: `${this.layoutDoc._notetaking_columns_autoSize ? 'Variable Size' : 'Autosize'} Columns`,
+                event: () => (this.layoutDoc._notetaking_columns_autoSize = !this.layoutDoc._notetaking_columns_autoSize),
+                icon: 'plus',
+            });
             subItems.push({ description: `${this.layoutDoc._layout_autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight), icon: 'plus' });
             subItems.push({ description: 'Clear All', event: () => (this.dataDoc.data = new List([])), icon: 'times' });
             ContextMenu.Instance.addItem({ description: 'Options...', subitems: subItems, icon: 'eye' });
@@ -634,6 +666,16 @@ export class CollectionNoteTakingView extends CollectionSubView() {
                 onContextMenu={this.onContextMenu}
                 onWheel={e => this._props.isContentActive() && e.stopPropagation()}>
                 <>{this.renderedSections}</>
+                <div className="collectionNotetaking-pivotField" style={{ right: 0, top: 0, position: 'absolute' }}>
+                    <FieldsDropdown
+                        Document={this.Document}
+                        selectFunc={undoable(fieldKey => {
+                            this.layoutDoc._pivotField = fieldKey;
+                            this.removeEmptyColumns();
+                        }, 'change pivot field')}
+                        placeholder={StrCast(this.layoutDoc._pivotField)}
+                    />
+                </div>
             </div>
         );
     }
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 788490b82..448b11b05 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -4,7 +4,6 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { lightOrDark, returnEmptyString } from '../../../Utils';
 import { Doc, DocListCast, Opt } from '../../../fields/Doc';
-import { Id } from '../../../fields/FieldSymbols';
 import { RichTextField } from '../../../fields/RichTextField';
 import { listSpec } from '../../../fields/Schema';
 import { SchemaHeaderField } from '../../../fields/SchemaHeaderField';
@@ -68,6 +67,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent<CSV
 
     // columnWidth returns the width of a column in absolute pixels
     @computed get columnWidth() {
+        if (this._props.Document._notetaking_columns_autoSize) return this._props.availableWidth / (this._props.colHeaderData?.length || 1);
         if (!this._props.colHeaderData || !this._props.headingObject || this._props.colHeaderData.length === 1) return `${(this._props.availableWidth / this._props.PanelWidth()) * 100}%`;
         const i = this._props.colHeaderData.findIndex(hd => hd.heading === this._props.headingObject?.heading && hd.color === this._props.headingObject.color);
         return ((this._props.colHeaderData[i].width * this._props.availableWidth) / this._props.PanelWidth()) * 100 + '%';
@@ -154,7 +154,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent<CSV
     deleteColumn = () => {
         const colHdrData = Array.from(Cast(this._props.Document[this._props.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null));
         if (this._props.headingObject) {
-            this._props.docList.forEach(d => (d[this._props.pivotField] = undefined));
+            //          this._props.docList.forEach(d => (d[DocData][this._props.pivotField] = undefined));
             colHdrData.splice(colHdrData.indexOf(this._props.headingObject), 1);
             this._props.resizeColumns(colHdrData);
         }
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index c2f3a6e4b..5c59f7f60 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1255,7 +1255,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
                 return !whichData ? undefined : { data: RTFCast(whichData), str: Field.toString(DocCast(whichData) ?? StrCast(whichData)) };
             },
             incomingValue => {
-                if (this._editorView && this._applyingChange !== this.fieldKey) {
+                if (this._editorView && this._applyingChange !== this.fieldKey && incomingValue?.data !== this.dataDoc[this.fieldKey]) {
                     if (incomingValue?.data) {
                         const updatedState = JSON.parse(incomingValue.data.Data);
                         if (JSON.stringify(this._editorView.state.toJSON()) !== JSON.stringify(updatedState)) {
-- 
cgit v1.2.3-70-g09d2

