From 733d16628dfc04316674d42c939b1077deb9bd31 Mon Sep 17 00:00:00 2001
From: ljungster <parkerljung@gmail.com>
Date: Thu, 16 Jun 2022 07:28:53 -0500
Subject: comitting before deleting comments

---
 .../collections/CollectionNoteTakingViewColumn.tsx | 337 +++++++++++++++++++++
 1 file changed, 337 insertions(+)
 create mode 100644 src/client/views/collections/CollectionNoteTakingViewColumn.tsx

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

diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
new file mode 100644
index 000000000..b299eb739
--- /dev/null
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -0,0 +1,337 @@
+import React = require("react");
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { action, computed, observable } from "mobx";
+import { observer } from "mobx-react";
+import { Doc, DocListCast, Opt } from "../../../fields/Doc";
+import { Id } from "../../../fields/FieldSymbols";
+import { RichTextField } from "../../../fields/RichTextField";
+import { SchemaHeaderField } from "../../../fields/SchemaHeaderField";
+import { ScriptField } from "../../../fields/ScriptField";
+import { ImageField } from "../../../fields/URLField";
+import { TraceMobx } from "../../../fields/util";
+import { emptyFunction, returnEmptyString, setupMoveUpEvents } from "../../../Utils";
+import { Docs, DocUtils } from "../../documents/Documents";
+import { DocumentType } from "../../documents/DocumentTypes";
+import { DragManager } from "../../util/DragManager";
+import { SnappingManager } from "../../util/SnappingManager";
+import { Transform } from "../../util/Transform";
+import { undoBatch } from "../../util/UndoManager";
+import { ContextMenu } from "../ContextMenu";
+import { ContextMenuProps } from "../ContextMenuItem";
+import { EditableView } from "../EditableView";
+import { FormattedTextBox } from "../nodes/formattedText/FormattedTextBox";
+import "./CollectionNoteTakingView.scss";
+const higflyout = require("@hig/flyout");
+export const { anchorPoints } = higflyout;
+export const Flyout = higflyout.default;
+
+// So this is how we are storing a column
+interface CSVFieldColumnProps {
+    Document: Doc;
+    DataDoc: Opt<Doc>;
+    docList: Doc[];
+    heading: string;
+    pivotField: string;
+    chromeHidden?: boolean;
+    columnHeaders: SchemaHeaderField[] | undefined;
+    headingObject: SchemaHeaderField | undefined;
+    yMargin: number;
+    // columnWidth: number;
+    numGroupColumns: number;
+    gridGap: number;
+    type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined;
+    headings: () => object[];
+    renderChildren: (docs: Doc[]) => JSX.Element[];
+    addDocument: (doc: Doc | Doc[]) => boolean;
+    createDropTarget: (ele: HTMLDivElement) => void;
+    screenToLocalTransform: () => Transform;
+    observeHeight: (myref: any) => void;
+    unobserveHeight: (myref: any) => void;
+    editableViewProps: any;
+    resizeColumns: (n: number) => void
+    columnStartXCoords: number[]
+    PanelWidth: number
+    maxColWidth: number
+    // docsByColumnHeader: Map<string, Doc[]>
+    // setDocsForColHeader: (key: string, docs: Doc[]) => void
+}
+
+@observer
+export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColumnProps> {
+    @observable private _background = "inherit";
+
+    @computed get columnWidth() {
+      // base cases
+      if (!this.props.columnHeaders || !this.props.headingObject || this.props.columnHeaders.length == 1) {
+        return this.props.maxColWidth
+      }
+      const i = this.props.columnHeaders.indexOf(this.props.headingObject)
+      if (i < 0) {
+        return this.props.maxColWidth
+      }
+      const endColValue = i == this.props.numGroupColumns - 1 ? this.props.PanelWidth : this.props.columnStartXCoords[i+1]
+      // TODO make the math work here. 35 is half of 70, which is the current width of the divider
+      return endColValue - this.props.columnStartXCoords[i] - 30
+    }
+
+    private dropDisposer?: DragManager.DragDropDisposer;
+    private _headerRef: React.RefObject<HTMLDivElement> = React.createRef();
+
+    @observable _heading = this.props.headingObject ? this.props.headingObject.heading : this.props.heading;
+    @observable _color = this.props.headingObject ? this.props.headingObject.color : "#f1efeb";
+    _ele: HTMLElement | null = null;
+
+    // This is likely similar to what we will be doing. Why do we need to make these refs?
+    // is that the only way to have drop targets?
+    createColumnDropRef = (ele: HTMLDivElement | null) => {
+        this.dropDisposer?.();
+        if (ele) {
+            this._ele = ele;
+            this.props.observeHeight(ele);
+            this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this));
+        }
+    }
+
+    componentWillUnmount() {
+        this.props.unobserveHeight(this._ele);
+    }
+
+    @undoBatch
+    columnDrop = action((e: Event, de: DragManager.DropEvent) => {
+        const drop = { docs: de.complete.docDragData?.droppedDocuments, val: this.getValue(this._heading) };
+        drop.docs?.forEach(d => Doc.SetInPlace(d, this.props.pivotField, drop.val, false));
+    });
+
+    getValue = (value: string): any => {
+        const parsed = parseInt(value);
+        if (!isNaN(parsed)) return parsed;
+        if (value.toLowerCase().indexOf("true") > -1) return true;
+        if (value.toLowerCase().indexOf("false") > -1) return false;
+        return value;
+    }
+
+    @action
+    headingChanged = (value: string, shiftDown?: boolean) => {
+        const castedValue = this.getValue(value);
+        if (castedValue) {
+            if (this.props.columnHeaders?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) {
+                return false;
+            }
+            this.props.docList.forEach(d => d[this.props.pivotField] = castedValue);
+            if (this.props.headingObject) {
+                this.props.headingObject.setHeading(castedValue.toString());
+                this._heading = this.props.headingObject.heading;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    @action pointerEntered = () => SnappingManager.GetIsDragging() && (this._background = "#b4b4b4");
+    @action pointerLeave = () => this._background = "inherit";
+    textCallback = (char: string) => this.addNewTextDoc("-typed text-", false, true);
+
+    @action
+    addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => {
+        if (!value && !forceEmptyNote) return false;
+        const key = this.props.pivotField;
+        const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, _fitWidth: true, title: value, _autoHeight: true });
+        const colValue = this.getValue(this.props.heading);
+        newDoc[key] = colValue;
+        FormattedTextBox.SelectOnLoad = newDoc[Id];
+        FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? "" : " ";
+        // let currentDocs: Doc[] = []
+        // const docsFromMap = this.props.docsByColumnHeader.get(colValue)
+        // if (docsFromMap) {
+        //   currentDocs = [...docsFromMap]
+        // }
+        // currentDocs.push(newDoc)
+        // this.props.setDocsForColHeader(colValue, currentDocs)
+        return this.props.addDocument?.(newDoc) || false;
+    }
+
+    @action
+    deleteColumn = () => {
+        if (!this.props.columnHeaders) {
+          return
+        }
+        if (this.props.headingObject) {
+          const index = this.props.columnHeaders.indexOf(this.props.headingObject);
+          const newIndex = index == 0 ? 1 : index - 1
+          const newHeader = this.props.columnHeaders[newIndex];
+          this.props.docList.forEach(d => d[this.props.pivotField] = newHeader.heading.toString())
+          this.props.columnHeaders.splice(index, 1);
+          this.props.resizeColumns(this.props.columnHeaders.length)
+        }
+    }
+
+    headerDown = (e: React.PointerEvent<HTMLDivElement>) => setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction);
+
+    //TODO: I think this is where I'm supposed to edit stuff 
+    startDrag = (e: PointerEvent, down: number[], delta: number[]) => {
+        console.log('in startDrag')
+        // is MakeAlias a way to make a copy of a doc without rendering it?
+        const alias = Doc.MakeAlias(this.props.Document);
+        // alias._width = this.props.columnWidth / (this.props.columnHeaders?.length || 1);
+        alias._width = this.columnWidth;
+        alias._pivotField = undefined;
+        let value = this.getValue(this._heading);
+        value = typeof value === "string" ? `"${value}"` : value;
+        alias.viewSpecScript = ScriptField.MakeFunction(`doc.${this.props.pivotField} === ${value}`, { doc: Doc.name });
+        if (alias.viewSpecScript) {
+            const options = {hideSource: false}
+            DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY, options);
+            console.log('in startDrag')
+            return true;
+        }
+        return false;
+    }
+
+    menuCallback = (x: number, y: number) => {
+        ContextMenu.Instance.clearItems();
+        const layoutItems: ContextMenuProps[] = [];
+        const docItems: ContextMenuProps[] = [];
+        const dataDoc = this.props.DataDoc || this.props.Document;
+        const pivotValue = this.getValue(this.props.heading);
+
+        DocUtils.addDocumentCreatorMenuItems((doc) => {
+            const key = this.props.pivotField;
+            doc[key] = this.getValue(this.props.heading);
+            FormattedTextBox.SelectOnLoad = doc[Id];
+            return this.props.addDocument?.(doc);
+        }, this.props.addDocument, x, y, true, this.props.pivotField, pivotValue);
+
+        Array.from(Object.keys(Doc.GetProto(dataDoc))).filter(fieldKey => dataDoc[fieldKey] instanceof RichTextField || dataDoc[fieldKey] instanceof ImageField || typeof (dataDoc[fieldKey]) === "string").map(fieldKey =>
+            docItems.push({
+                description: ":" + fieldKey, event: () => {
+                    const created = DocUtils.DocumentFromField(dataDoc, fieldKey, Doc.GetProto(this.props.Document));
+                    if (created) {
+                        if (this.props.Document.isTemplateDoc) {
+                            Doc.MakeMetadataFieldTemplate(created, this.props.Document);
+                        }
+                        return this.props.addDocument?.(created);
+                    }
+                }, icon: "compress-arrows-alt"
+            }));
+        Array.from(Object.keys(Doc.GetProto(dataDoc))).filter(fieldKey => DocListCast(dataDoc[fieldKey]).length).map(fieldKey =>
+            docItems.push({
+                description: ":" + fieldKey, event: () => {
+                    const created = Docs.Create.CarouselDocument([], { _width: 400, _height: 200, title: fieldKey });
+                    if (created) {
+                        const container = this.props.Document.resolvedDataDoc ? Doc.GetProto(this.props.Document) : this.props.Document;
+                        if (container.isTemplateDoc) {
+                            Doc.MakeMetadataFieldTemplate(created, container);
+                            return Doc.AddDocToList(container, Doc.LayoutFieldKey(container), created);
+                        }
+                        return this.props.addDocument?.(created) || false;
+                    }
+                }, icon: "compress-arrows-alt"
+            }));
+        !Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ description: "Doc Fields ...", subitems: docItems, icon: "eye" });
+        !Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ description: "Containers ...", subitems: layoutItems, icon: "eye" });
+        ContextMenu.Instance.setDefaultItem("::", (name: string): void => {
+            Doc.GetProto(this.props.Document)[name] = "";
+            const created = Docs.Create.TextDocument("", { title: name, _width: 250, _autoHeight: true });
+            if (created) {
+                if (this.props.Document.isTemplateDoc) {
+                    Doc.MakeMetadataFieldTemplate(created, this.props.Document);
+                }
+                this.props.addDocument?.(created);
+            }
+        });
+        ContextMenu.Instance.displayMenu(x, y, undefined, true);
+    }
+
+    @computed get innards() {
+        TraceMobx();
+        const key = this.props.pivotField;
+        const heading = this._heading;
+        const columnYMargin = this.props.headingObject ? 0 : this.props.yMargin;
+        const evContents = heading ? heading : "25";
+        const headingView = this.props.headingObject ?
+            <div key={heading} className="collectionNoteTakingView-sectionHeader" ref={this._headerRef}
+                style={{
+                    marginTop: 2 * this.props.yMargin,
+                    // width: (this.props.columnWidth) /
+                    //     ((uniqueHeadings.length) || 1)
+                    width: this.columnWidth - 20
+                }}>
+                <div className="collectionNoteTakingView-sectionHeader-subCont" onPointerDown={this.headerDown}
+                    title={evContents === `No Value` ?
+                        `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ""}
+                    style={{ background: evContents !== `No Value` ? this._color : "inherit" }}>
+                    <EditableView
+                        GetValue={() => evContents}
+                        SetValue={this.headingChanged}
+                        contents={evContents}
+                        oneLine={true}
+                    />
+                </div>
+            </div> : (null);
+        // const templatecols = `${this.props.columnWidth / this.props.numGroupColumns}px `;
+        const templatecols = `${this.columnWidth}px `;
+        const type = this.props.Document.type;
+        return <>
+            {headingView}
+            {<div>
+              <div key={`${heading}-stack`} className={`collectionNoteTakingView-Nodes`}
+                  style={{
+                      padding: `${columnYMargin}px ${0}px ${this.props.yMargin}px ${0}px`,
+                      margin: "auto",
+                      width: "max-content", //singleColumn ? undefined : `${cols * (style.columnWidth + style.gridGap) + 2 * style.xMargin - style.gridGap}px`,
+                      height: 'max-content',
+                      position: "relative",
+                      gridGap: this.props.gridGap,
+                      gridTemplateColumns: templatecols,
+                      gridAutoRows: "0px"
+                  }}>
+                  {this.props.renderChildren(this.props.docList)}
+              </div>
+
+              {!this.props.chromeHidden && type !== DocumentType.PRES ?
+                  <div className="collectionNoteTakingView-DocumentButtons"
+                      // style={{ width: this.props.columnWidth / this.props.numGroupColumns, marginBottom: 10 }}>
+                      style={{ width: this.columnWidth - 20, marginBottom: 10 }}>
+                      <div key={`${heading}-add-document`} className="collectionNoteTakingView-addDocumentButton">
+                          <EditableView
+                              GetValue={returnEmptyString}
+                              SetValue={this.addNewTextDoc}
+                              textCallback={this.textCallback}
+                              placeholder={"Type ':' for commands"}
+                              contents={"+ New Node"}
+                              menuCallback={this.menuCallback}
+                          />
+                      </div>
+                      <div key={`${this.props.Document[Id]}-addGroup`} className="collectionNoteTakingView-addDocumentButton">
+                          <EditableView {...this.props.editableViewProps} />
+                      </div>
+                      {(this.props.columnHeaders?.length && this.props.columnHeaders.length > 1) && 
+                          <button className="collectionNoteTakingView-sectionDelete" onClick={this.deleteColumn}>
+                          <FontAwesomeIcon icon="trash" size="lg" />
+                      </button>
+                      }
+                  </div>
+                  : null}
+              </div>
+            }
+        </>;
+    }
+
+
+    render() {
+        TraceMobx();
+        const heading = this._heading;
+        return (
+            <div className={"collectionNoteTakingViewFieldColumn" + (SnappingManager.GetIsDragging() ? "Dragging" : "")} key={heading}
+                style={{
+                  //TODO: change this so that it's based on the column width 
+                    width: this.columnWidth,
+                    height: "100%",
+                    background: this._background
+                }}
+                ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}>
+                {this.innards}
+            </div >
+        );
+    }
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 323f846d035e78e729f918ccf2681f5f0834d98e Mon Sep 17 00:00:00 2001
From: ljungster <parkerljung@gmail.com>
Date: Wed, 22 Jun 2022 10:08:08 -0500
Subject: push before switching to childDocList

---
 .../views/collections/CollectionNoteTakingView.tsx | 105 ++++++---------------
 .../collections/CollectionNoteTakingViewColumn.tsx |   7 --
 2 files changed, 30 insertions(+), 82 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 97fc5cc7c..302e7c890 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -97,7 +97,6 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     // [CAVEATS] (1) keep track of the offsetting
     // (2) documentView gets unmounted as you remove it from the list
     get Sections() {
-        if (this.columnHeaders instanceof Promise) return new Map<SchemaHeaderField, Doc[]>();
         const columnHeaders = this.columnHeaders;
         const sections = new Map<SchemaHeaderField, Doc[]>(columnHeaders.map(sh => [sh, []] as [SchemaHeaderField, []]));
         let docs = this.childDocs
@@ -337,8 +336,6 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     @action
     onPointerOver = (e: React.PointerEvent) => {
       if (DragManager.docsBeingDragged.length && this.childDocList) {
-        //TODO: update new observable field to empty slice once done
-        //TODO: how do we update the docs in the column once we switch over?
         // get the current docs for the column based on the mouse's x coordinate
         // will use again later, which is why we're saving as local
         const xCoord = e.clientX - 2 * this.gridGap
@@ -347,48 +344,31 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         const clientY = e.clientY
         let dropInd = -1;
         // unsure whether we still want this dropAfter field
-        let dropAfter = 0;
+        // let dropAfter = 0;
         // manually set to 140, because not sure how to get exact value
         let pos0 = 140
         colDocs.forEach((doc, i) => {
-          //TODO: this isn't getting the actual positions of the doc like I thought it would
-          // const width = () => this.getDocWidth(doc);
-          // const displayDoc = this.getDisplayDoc(doc, width)
-          // const dref = displayDoc.props.dref
           const noteTakingDocTransform = () => this.getDocTransform(doc);
-          // const pos0 = noteTakingDocTransform().inverse().transformPoint(0, 0);
           let pos1 = noteTakingDocTransform().inverse().transformPoint(0, this.getDocHeight(doc) + 2 * this.gridGap)[1];
           pos1 += pos0
           // updating drop position based on y coordinates
           const yCoordInBetween = clientY > pos0 && (clientY < pos1 || i == colDocs.length - 1)
           if (yCoordInBetween) {
             dropInd = i;
-            dropAfter = 0;
+            // dropAfter = 0;
             if (clientY > (pos0 + pos1) / 2) {
-              dropAfter = 1;
+              // dropAfter = 1;
             }
           }
           pos0 = pos1
         })
+        // 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)
+        // DragManager.docsBeingDragged.forEach(d => d[this.pivotField] = colHeader)
+        // used to notify sections to re-render
+        console.log([dropInd, this.getColumnFromXCoord(xCoord)])
         this.docsDraggedRowCol = [dropInd, this.getColumnFromXCoord(xCoord)]
-        console.log(`[${this.docsDraggedRowCol[0]}, ${this.docsDraggedRowCol[1]}]`)
-
-        // since we have row, col, we can send that to an observable value in NoteTaking view
-
-
-        // TODO: add the doc back into the proper position and then update childDocs list
-        // Need to update our list of all docs to properly 
-        // const docs = this.childDocList;
-        // const docs = this.childDocs;
-
-        // 
-        // const newDocs = DragManager.docsBeingDragged;
-        // if (docs && newDocs.length) {
-        //   const insertInd = dropInd === -1 ? docs.length : dropInd + dropAfter;
-        //   const offset = newDocs.reduce((off, ndoc) => this.filteredChildren.find((fdoc, i) => ndoc === fdoc && i < insertInd) ? off + 1 : off, 0);
-        //   newDocs.filter(ndoc => docs.indexOf(ndoc) !== -1).forEach(ndoc => docs.splice(docs.indexOf(ndoc), 1));
-        //   docs.splice(insertInd - offset, 0, ...newDocs);
-        // }
       }
     }
 
@@ -426,58 +406,33 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
       return docsMatchingHeader;
     }
 
-
     @undoBatch
     @action
     onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
-        const where = [de.x, de.y];
-        let dropInd = -1;
-        let dropAfter = 0;
         if (de.complete.docDragData) {
-            // const docs = this.getDocsFromXCoord(de.x)
-            const docs = this.childDocs
-            docs.map((d, i) => {
-              const pos0 = this.getDocTransform(d).inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap);
-              const pos1 = this.getDocTransform(d).inverse().transformPoint(this.getDocWidth(d), this.getDocHeight(d));
-              // const pos = d.noteTakingDocTransform().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap);
-              // const pos1 = cd.noteTakingDocTransform().inverse().transformPoint(cd.width(), cd.height());
-              // const top = cd.height();
-              // const pos = cd.noteTakingDocTransform().transformPoint(0, cd.height());
-              // TODO: plan
-              // Get the top of the box
-              // Check if there could possibly be a box below
-              
-              // const pos1 = cd.noteTakingDocTransform().transformPoint(0, cd.height());
-              // if (where[0] > pos[0] && where[0] < pos1[0] && where[1] > pos[1] && (i === this._docXfs.length - 1 || where[1] < pos1[1])) {
-              if (where[1] > pos0[1] && (i === docs.length - 1 || where[1] < pos1[1])) {
-                  dropInd = i;
-                  const axis = 1;
-                  dropAfter = where[axis] > (pos0[axis] + pos1[axis]) / 2 ? 1 : 0;
-              }
-          });
-            //TODO: all of this is wrong
-            const oldDocs = this.childDocs.length;
             if (super.onInternalDrop(e, de)) {
-              // check to see if we actually need anything to the new column of nodes (if droppedDocs != empty)
-                const droppedDocs = this.childDocs.slice().filter((d: Doc, ind: number) => ind >= oldDocs); // if the drop operation adds something to the end of the list, then use that as the new document (may be different than what was dropped e.g., in the case of a button which is dropped but which creates say, a note).
-                const newDocs = droppedDocs.length ? droppedDocs : de.complete.docDragData.droppedDocuments; // if nothing was added to the end of the list, then presumably the dropped documents were already in the list, but possibly got reordered so we use them.
-
-                const docs = this.childDocList;
-                // reset drag manager docs, because we just dropped
-                DragManager.docsBeingDragged = [];
-                // TODO: I don't think we will actually need any of this, but doesn't hurt to be sure.
-                if (docs && newDocs.length) {
-                    const insertInd = dropInd === -1 ? docs.length : dropInd + dropAfter;
-                    const offset = newDocs.reduce((off, ndoc) => this.filteredChildren.find((fdoc, i) => ndoc === fdoc && i < insertInd) ? off + 1 : off, 0);
-                    newDocs.filter(ndoc => docs.indexOf(ndoc) !== -1).forEach(ndoc => docs.splice(docs.indexOf(ndoc), 1));
-                    // doesn't appear to be causing issues, but potentially could create
-                    // if (this.placeHolderDown) {
-                    //   docs.splice(0, 1);
-                    //   this.placeHolderDown = false
-                    // }
-                    docs.splice(insertInd - offset, 0, ...newDocs);
-                }
+              DragManager.docsBeingDragged = []
               this.docsDraggedRowCol = []
+              // filter out the currently dragged docs from the child docs, since we will insert them later
+              const rowCol = this.docsDraggedRowCol
+              const droppedDocs = this.childDocs.slice().filter((d: Doc, ind: number) => ind >= this.childDocs.length); // if the drop operation adds something to the end of the list, then use that as the new document (may be different than what was dropped e.g., in the case of a button which is dropped but which creates say, a note).
+              const newDocs = droppedDocs.length ? droppedDocs : de.complete.docDragData.droppedDocuments;
+              
+              const docs = this.childDocs
+              if (docs && newDocs.length) {
+                // remove the dragged documents from the childDocList
+                newDocs.filter(d => docs.indexOf(d) !== -1).forEach(d => docs.splice(docs.indexOf(d), 1))
+                // if the doc starts a columnm (or the drop index is undefined), we can just push it to the back. Otherwise we need to add it to the column properly
+                if (rowCol[0] <= 0) {
+                  docs.splice(docs.length - 1, 0, ...newDocs)
+                } else {
+                  const colDocs = this.getDocsFromXCoord(de.x)
+                  const previousDoc = colDocs[rowCol[0] - 1]
+                  const previousDocIndex = this.childDocs.findIndex(d => {d[Id] == previousDoc[Id]})
+                  //TODO: removing the doc instead of doing what we expect it to do
+                  docs.splice(previousDocIndex, 0, ...newDocs)
+                }
+              }
             }
         } // it seems like we're creating a link here. Weird. I didn't know that you could establish links by dragging
         else if (de.complete.linkDragData?.dragDocument.context === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) {
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index b299eb739..bdcb9c399 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -140,13 +140,6 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
         newDoc[key] = colValue;
         FormattedTextBox.SelectOnLoad = newDoc[Id];
         FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? "" : " ";
-        // let currentDocs: Doc[] = []
-        // const docsFromMap = this.props.docsByColumnHeader.get(colValue)
-        // if (docsFromMap) {
-        //   currentDocs = [...docsFromMap]
-        // }
-        // currentDocs.push(newDoc)
-        // this.props.setDocsForColHeader(colValue, currentDocs)
         return this.props.addDocument?.(newDoc) || false;
     }
 
-- 
cgit v1.2.3-70-g09d2


From 55bac585fa0b8d6c3f513ccecb22456d1d361040 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 3 Aug 2022 13:33:38 -0400
Subject: fixes for dragging notes so that they highlight properly and go to
 the right place when embedded in freeform views.

---
 src/client/documents/Documents.ts                  |   9 +-
 src/client/util/CurrentUserUtils.ts                |   3 +-
 src/client/util/DragManager.ts                     |  12 +-
 src/client/views/DocumentDecorations.tsx           |   2 +-
 src/client/views/StyleProvider.tsx                 |   8 +-
 .../views/collections/CollectionNoteTakingView.tsx |  91 +++---
 .../collections/CollectionNoteTakingViewColumn.tsx | 358 +++++++++++----------
 .../CollectionNoteTakingViewDivider.tsx            | 112 +++----
 .../views/collections/CollectionStackingView.tsx   |   4 +-
 src/client/views/nodes/DocumentView.tsx            |  30 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |   6 +-
 11 files changed, 332 insertions(+), 303 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 32d7152fd..9d00664ad 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -1036,7 +1036,14 @@ export namespace Docs {
         }
 
         export function NoteTakingDocument(documents: Array<Doc>, options: DocumentOptions, id?: string, protoId?: string) {
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.NoteTaking }, id, undefined, protoId);
+            return InstanceFromProto(
+                Prototypes.get(DocumentType.COL),
+                new List(documents),
+                { columnHeaders: new List<SchemaHeaderField>([new SchemaHeaderField('Untitled')]), ...options, _viewType: CollectionViewType.NoteTaking },
+                id,
+                undefined,
+                protoId
+            );
         }
 
         export function MulticolumnDocument(documents: Array<Doc>, options: DocumentOptions) {
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 28dc44c25..7856c913b 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -135,7 +135,6 @@ export class CurrentUserUtils {
         return DocUtils.AssignOpts(tempClicks, reqdOpts, reqdClickList) ?? (doc[field] = Docs.Create.TreeDocument(reqdClickList, reqdOpts));
     }
 
-
     /// Initializes templates that can be applied to notes
     static setupNoteTemplates(doc: Doc, field="template-notes") {
         const tempNotes = DocCast(doc[field]);
@@ -255,6 +254,7 @@ export class CurrentUserUtils {
                           creator:(opts:DocumentOptions)=> any // how to create the empty thing if it doesn't exist
               }[] = [
             {key: "Note",       creator: opts => Docs.Create.TextDocument("", opts),        opts: { _width: 200, _autoHeight: true }},
+            {key: "Noteboard",  creator: opts => Docs.Create.NoteTakingDocument([], opts),  opts: { _width: 250, _height: 200 }},
             {key: "Collection", creator: opts => Docs.Create.FreeformDocument([], opts),    opts: { _width: 150, _height: 100 }},
             {key: "Equation",   creator: opts => Docs.Create.EquationDocument(opts),        opts: { _width: 300, _height: 35, _fitWidth:false, _backgroundGridShow: true, }},
             {key: "Webpage",    creator: opts => Docs.Create.WebDocument("",opts),          opts: { _width: 400, _height: 512, _nativeWidth: 850, useCors: true, }},
@@ -280,6 +280,7 @@ export class CurrentUserUtils {
         
         return [
             { toolTip: "Tap or drag to create a note",            title: "Note", icon: "sticky-note",   dragFactory: doc.emptyNote as Doc, },
+            { toolTip: "Tap or drag to create a note board",      title: "Notes", icon: "folder",       dragFactory: doc.emptyNoteboard as Doc, },
             { toolTip: "Tap or drag to create a collection",      title: "Col", icon: "folder",         dragFactory: doc.emptyCollection as Doc, clickFactory: DocCast(doc.emptyTab),  scripts: { onClick: 'openOnRight(copyDragFactory(this.clickFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, },
             { toolTip: "Tap or drag to create an equation",       title: "Math", icon: "calculator",    dragFactory: doc.emptyEquation as Doc, },
             { toolTip: "Tap or drag to create a webpage",         title: "Web", icon: "globe-asia",     dragFactory: doc.emptyWebpage as Doc, },
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 3a1bb1673..f4987cf34 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -1,4 +1,4 @@
-import { action } from 'mobx';
+import { action, observable, runInAction } from 'mobx';
 import { DateField } from '../../fields/DateField';
 import { Doc, Field, Opt } from '../../fields/Doc';
 import { List } from '../../fields/List';
@@ -320,7 +320,7 @@ export namespace DragManager {
             y: snapVal([yFromTop, yFromBottom], e.pageY, SnappingManager.horizSnapLines()),
         };
     }
-    export let docsBeingDragged: Doc[] = [];
+    export let docsBeingDragged: Doc[] = observable([] as Doc[]);
     export let CanEmbed = false;
     export let DocDragData: DocumentDragData | undefined;
     export function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: DragCompleteEvent) => void) {
@@ -349,13 +349,13 @@ export namespace DragManager {
             xs: number[] = [],
             ys: number[] = [];
 
-        docsBeingDragged = dragData instanceof DocumentDragData ? dragData.draggedDocuments : dragData instanceof AnchorAnnoDragData ? [dragData.dragDocument] : [];
         const elesCont = {
             left: Number.MAX_SAFE_INTEGER,
             right: Number.MIN_SAFE_INTEGER,
             top: Number.MAX_SAFE_INTEGER,
             bottom: Number.MIN_SAFE_INTEGER,
         };
+        const docsToDrag = dragData instanceof DocumentDragData ? dragData.draggedDocuments : dragData instanceof AnchorAnnoDragData ? [dragData.dragDocument] : [];
         const dragElements = eles.map(ele => {
             if (!ele.parentNode) dragDiv.appendChild(ele);
             const dragElement = ele.parentNode === dragDiv ? ele : (ele.cloneNode(true) as HTMLElement);
@@ -405,7 +405,7 @@ export namespace DragManager {
             });
             dragLabel.style.transform = `translate(${rect.left + (options?.offsetX || 0)}px, ${rect.top + (options?.offsetY || 0) - 20}px)`;
 
-            if (docsBeingDragged.length) {
+            if (docsToDrag.length) {
                 const pdfBox = dragElement.getElementsByTagName('canvas');
                 const pdfBoxSrc = ele.getElementsByTagName('canvas');
                 Array.from(pdfBox)
@@ -429,6 +429,8 @@ export namespace DragManager {
             return dragElement;
         });
 
+        runInAction(() => docsBeingDragged.push(...docsToDrag));
+
         const hideDragShowOriginalElements = (hide: boolean) => {
             dragLabel.style.display = hide ? '' : 'none';
             !hide && dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement));
@@ -456,7 +458,7 @@ export namespace DragManager {
             SnappingManager.SetIsDragging(false);
             SnappingManager.clearSnapLines();
             batch.end();
-            docsBeingDragged = [];
+            docsBeingDragged.length = 0;
         });
         var startWindowDragTimer: any;
         const moveHandler = (e: PointerEvent) => {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index c53e61699..0db9eab69 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -351,7 +351,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
 
     @action
     onPointerDown = (e: React.PointerEvent): void => {
-        DragManager.docsBeingDragged = SelectionManager.Views().map(dv => dv.rootDoc);
+        DragManager.docsBeingDragged.push(...SelectionManager.Views().map(dv => dv.rootDoc));
         this._inkDragDocs = DragManager.docsBeingDragged
             .filter(doc => doc.type === DocumentType.INK)
             .map(doc => {
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 692f7b98e..a83163eb0 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -110,8 +110,8 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             return undefined;
         case StyleProp.WidgetColor:
             return isAnnotated ? Colors.LIGHT_BLUE : darkScheme() ? 'lightgrey' : 'dimgrey';
-            // return doc = dragManager.dragDocument ? props.dragEffects.opacity??CastofOpacityonline94 : Cast())
-            // same idea for background Color
+        // return doc = dragManager.dragDocument ? props.dragEffects.opacity??CastofOpacityonline94 : Cast())
+        // same idea for background Color
         case StyleProp.Opacity:
             return Cast(doc?._opacity, 'number', Cast(doc?.opacity, 'number', null));
         case StyleProp.HideLinkButton:
@@ -156,7 +156,9 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
         case StyleProp.JitterRotation:
             return comicStyle() ? random(-1, 1, NumCast(doc?.x), NumCast(doc?.y)) * ((props?.PanelWidth() || 0) > (props?.PanelHeight() || 0) ? 5 : 10) : 0;
         case StyleProp.HeaderMargin:
-            return ([CollectionViewType.Stacking, CollectionViewType.NoteTaking, CollectionViewType.Masonry, CollectionViewType.Tree].includes(doc?._viewType as any) || (doc?.type === DocumentType.RTF && !showTitle()?.includes('noMargin')) || doc?.type === DocumentType.LABEL) &&
+            return ([CollectionViewType.Stacking, CollectionViewType.NoteTaking, CollectionViewType.Masonry, CollectionViewType.Tree].includes(doc?._viewType as any) ||
+                (doc?.type === DocumentType.RTF && !showTitle()?.includes('noMargin')) ||
+                doc?.type === DocumentType.LABEL) &&
                 showTitle() &&
                 !StrCast(doc?.showTitle).includes(':hover')
                 ? 15
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index f442559fb..1854a4213 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -1,6 +1,6 @@
 import React = require('react');
 import { CursorProperty } from 'csstype';
-import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import { DataSym, Doc, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
 import { Id } from '../../../fields/FieldSymbols';
@@ -21,10 +21,12 @@ 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';
 import { StyleProp } from '../StyleProvider';
 import './CollectionNoteTakingView.scss';
 import { CollectionNoteTakingViewColumn } from './CollectionNoteTakingViewColumn';
-import CollectionNoteTakingViewDivider from './CollectionNoteTakingViewDivider';
+import { CollectionNoteTakingViewDivider } from './CollectionNoteTakingViewDivider';
 import { CollectionSubView } from './CollectionSubView';
 const _global = (window /* browser */ || global) /* node */ as any;
 
@@ -40,7 +42,6 @@ export type collectionNoteTakingViewProps = {
 
 @observer
 export class CollectionNoteTakingView extends CollectionSubView<Partial<collectionNoteTakingViewProps>>() {
-    _pivotFieldDisposer?: IReactionDisposer;
     _autoHeightDisposer?: IReactionDisposer;
     _masonryGridRef: HTMLDivElement | null = null;
     _draggerRef = React.createRef<HTMLDivElement>();
@@ -54,10 +55,10 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         return this.props.chromeHidden || BoolCast(this.layoutDoc.chromeHidden);
     }
     @computed get columnHeaders() {
-        return Cast(this.layoutDoc._columnHeaders, listSpec(SchemaHeaderField), null);
+        return Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null);
     }
-    @computed get pivotField() {
-        return 'Col';
+    @computed get notetakingCategoryField() {
+        return 'noteTakingCategory';
     }
     @computed get filteredChildren() {
         return this.childLayoutPairs.filter(pair => pair.layout instanceof Doc && !pair.layout.hidden).map(pair => pair.layout);
@@ -90,7 +91,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     constructor(props: any) {
         super(props);
         if (this.columnHeaders === undefined) {
-            this.layoutDoc._columnHeaders = new List<SchemaHeaderField>([new SchemaHeaderField('New Column')]);
+            this.dataDoc.columnHeaders = new List<SchemaHeaderField>([new SchemaHeaderField('New Column')]);
             this.columnStartXCoords = [0];
             // add all of the docs that have not been added to a column to this new column
         } else {
@@ -126,18 +127,16 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         // filter out the currently dragged docs from the child docs, since we will insert them later
         if (rowCol.length && DragManager.docsBeingDragged.length) {
             const docIdsToRemove = new Set();
-            DragManager.docsBeingDragged.forEach(d => {
-                docIdsToRemove.add(d[Id]);
-            });
+            DragManager.docsBeingDragged.forEach(d => docIdsToRemove.add(d[Id]));
             docs = docs.filter(d => !docIdsToRemove.has(d[Id]));
         }
 
         // this will sort the docs into the correct columns (minus the ones you're currently dragging)
         docs.map(d => {
-            if (!d[this.pivotField]) {
-                d[this.pivotField] = columnHeaders.length > 0 ? columnHeaders[0].heading : `New Column`;
+            if (!d[this.notetakingCategoryField]) {
+                d[this.notetakingCategoryField] = columnHeaders.length > 0 ? columnHeaders[0].heading : `New Column`;
             }
-            const sectionValue = d[this.pivotField] as object;
+            const sectionValue = d[this.notetakingCategoryField] as object;
 
             // look for if header exists already
             const existingHeader = columnHeaders.find(sh => sh.heading === sectionValue.toString());
@@ -156,14 +155,15 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         return sections;
     }
 
+    removeDocDragHighlight = () => {
+        setTimeout(
+            action(() => (this.docsDraggedRowCol.length = 0)),
+            100
+        );
+    };
     componentDidMount() {
         super.componentDidMount?.();
-        // reset section headers when a new filter is inputted
-        this._pivotFieldDisposer = reaction(
-            () => this.pivotField,
-            () => (this.layoutDoc._columnHeaders = new List())
-        );
-
+        document.addEventListener('pointerup', this.removeDocDragHighlight, true);
         this._autoHeightDisposer = reaction(
             () => this.layoutDoc._autoHeight,
             autoHeight => autoHeight && this.props.setHeight?.(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), this.headerMargin + Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', ''))))))
@@ -171,8 +171,8 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     }
 
     componentWillUnmount() {
+        document.removeEventListener('pointerup', this.removeDocDragHighlight, true);
         super.componentWillUnmount();
-        this._pivotFieldDisposer?.();
         this._autoHeightDisposer?.();
     }
 
@@ -227,6 +227,9 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     };
 
     styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string) => {
+        if (property === StyleProp.BoxShadow && doc && DragManager.docsBeingDragged.includes(doc)) {
+            return `#9c9396  ${StrCast(doc?.boxShadow, '10px 10px 0.9vw')}`;
+        }
         if (property === StyleProp.Opacity && doc) {
             if (this.props.childOpacity) {
                 return this.props.childOpacity();
@@ -258,9 +261,9 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
                 docViewPath={this.props.docViewPath}
                 fitWidth={this.props.childFitWidth}
                 isContentActive={emptyFunction}
-                originalBackgroundColor={StrCast(doc.backgroundColor)}
+                onKey={this.onKeyDown}
                 //TODO: change this from a prop to a parameter passed into a function
-                isNoteTakingView={true}
+                dontHideOnDrag={true}
                 isDocumentActive={this.isContentActive}
                 LayoutTemplate={this.props.childLayoutTemplate}
                 LayoutTemplateString={this.props.childLayoutString}
@@ -307,7 +310,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     // how to get the width of a document. Currently returns the width of the column (minus margins)
     // if a note doc. Otherwise, returns the normal width (for graphs, images, etc...)
     getDocWidth(d: Doc) {
-        const heading = d[this.pivotField] as object;
+        const heading = d[this.notetakingCategoryField] as object;
         const castedSectionValue = heading.toString();
         const existingHeader = this.columnHeaders.find(sh => sh.heading === castedSectionValue);
         const colStartXCoords = this.columnStartXCoords;
@@ -364,20 +367,14 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         if (DragManager.docsBeingDragged.length && this.childDocList) {
             // get the current docs for the column based on the mouse's x coordinate
             // will use again later, which is why we're saving as local
-            const xCoord = e.clientX - 2 * this.gridGap;
+            const xCoord = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0] - 2 * this.gridGap;
             const colDocs = this.getDocsFromXCoord(xCoord);
             // get the index for where you need to insert the doc you are currently dragging
-            const clientY = e.clientY;
+            const clientY = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[1];
             let dropInd = -1;
-            // unsure whether we still want this dropAfter field
-            // let dropAfter = 0;
-            // manually set to 140, because not sure how to get exact value
-            let pos0 = 140;
+            let pos0 = (this.refList.lastElement() as HTMLDivElement).children[0].getBoundingClientRect().height + this.yMargin * 2;
             colDocs.forEach((doc, i) => {
-                const noteTakingDocTransform = () => this.getDocTransform(doc);
-                let pos1 = noteTakingDocTransform()
-                    .inverse()
-                    .transformPoint(0, this.getDocHeight(doc) + 2 * this.gridGap)[1];
+                let pos1 = this.getDocHeight(doc) + 2 * this.gridGap;
                 pos1 += pos0;
                 // updating drop position based on y coordinates
                 const yCoordInBetween = clientY > pos0 && (clientY < pos1 || i == colDocs.length - 1);
@@ -393,10 +390,10 @@ 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);
-            DragManager.docsBeingDragged.forEach(d => (d[this.pivotField] = colHeader));
+            DragManager.docsBeingDragged.forEach(d => (d[this.notetakingCategoryField] = colHeader));
             // used to notify sections to re-render
-            // console.log([dropInd, this.getColumnFromXCoord(xCoord)])
-            this.docsDraggedRowCol = [dropInd, this.getColumnFromXCoord(xCoord)];
+            this.docsDraggedRowCol.length = 0;
+            this.docsDraggedRowCol.push(dropInd, this.getColumnFromXCoord(xCoord));
         }
     };
 
@@ -425,7 +422,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         if (docs) {
             docs.map(d => {
                 if (d instanceof Promise) return;
-                const sectionValue = d[this.pivotField] as object;
+                const sectionValue = d[this.notetakingCategoryField] as object;
                 if (sectionValue.toString() == colHeader) {
                     docsMatchingHeader.push(d);
                 }
@@ -434,13 +431,24 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         return docsMatchingHeader;
     };
 
+    @undoBatch
+    @action
+    onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => {
+        const docView = fieldProps.DocumentView?.();
+        if (docView && (e.ctrlKey || docView.rootDoc._singleLine) && ['Enter'].includes(e.key)) {
+            e.stopPropagation?.();
+            const newDoc = Doc.MakeCopy(docView.rootDoc, true);
+            Doc.GetProto(newDoc).text = undefined;
+            FormattedTextBox.SelectOnLoad = newDoc[Id];
+            return this.addDocument?.(newDoc);
+        }
+    };
+
     @undoBatch
     @action
     onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
         if (de.complete.docDragData) {
             if (super.onInternalDrop(e, de)) {
-                DragManager.docsBeingDragged = [];
-                // this.docsDraggedRowCol = []
                 // filter out the currently dragged docs from the child docs, since we will insert them later
                 const rowCol = this.docsDraggedRowCol;
                 const droppedDocs = this.childDocs.slice().filter((d: Doc, ind: number) => ind >= this.childDocs.length); // if the drop operation adds something to the end of the list, then use that as the new document (may be different than what was dropped e.g., in the case of a button which is dropped but which creates say, a note).
@@ -456,10 +464,9 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
                     if (rowCol[0] <= 0) {
                         docs.splice(0, 0, ...newDocs);
                     } else {
-                        const colDocs = this.getDocsFromXCoord(de.x);
+                        const colDocs = this.getDocsFromXCoord(this.props.ScreenToLocalTransform().transformPoint(de.x, de.y)[0]);
                         const previousDoc = colDocs[rowCol[0] - 1];
                         const previousDocIndex = docs.indexOf(previousDoc);
-                        console.log(`docs: ${previousDocIndex}`);
                         docs.splice(previousDocIndex + 1, 0, ...newDocs);
                     }
                 }
@@ -561,7 +568,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
                 renderChildren={this.children}
                 numGroupColumns={this.numGroupColumns}
                 gridGap={this.gridGap}
-                pivotField={this.pivotField}
+                pivotField={this.notetakingCategoryField}
                 columnStartXCoords={this.columnStartXCoords}
                 maxColWidth={this.maxColWdith}
                 PanelWidth={this.PanelWidth}
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index bdcb9c399..55d032498 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -1,27 +1,27 @@
-import React = require("react");
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, computed, observable } from "mobx";
-import { observer } from "mobx-react";
-import { Doc, DocListCast, Opt } from "../../../fields/Doc";
-import { Id } from "../../../fields/FieldSymbols";
-import { RichTextField } from "../../../fields/RichTextField";
-import { SchemaHeaderField } from "../../../fields/SchemaHeaderField";
-import { ScriptField } from "../../../fields/ScriptField";
-import { ImageField } from "../../../fields/URLField";
-import { TraceMobx } from "../../../fields/util";
-import { emptyFunction, returnEmptyString, setupMoveUpEvents } from "../../../Utils";
-import { Docs, DocUtils } from "../../documents/Documents";
-import { DocumentType } from "../../documents/DocumentTypes";
-import { DragManager } from "../../util/DragManager";
-import { SnappingManager } from "../../util/SnappingManager";
-import { Transform } from "../../util/Transform";
-import { undoBatch } from "../../util/UndoManager";
-import { ContextMenu } from "../ContextMenu";
-import { ContextMenuProps } from "../ContextMenuItem";
-import { EditableView } from "../EditableView";
-import { FormattedTextBox } from "../nodes/formattedText/FormattedTextBox";
-import "./CollectionNoteTakingView.scss";
-const higflyout = require("@hig/flyout");
+import React = require('react');
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { action, computed, observable } from 'mobx';
+import { observer } from 'mobx-react';
+import { Doc, DocListCast, Opt } from '../../../fields/Doc';
+import { Id } from '../../../fields/FieldSymbols';
+import { RichTextField } from '../../../fields/RichTextField';
+import { SchemaHeaderField } from '../../../fields/SchemaHeaderField';
+import { ScriptField } from '../../../fields/ScriptField';
+import { ImageField } from '../../../fields/URLField';
+import { TraceMobx } from '../../../fields/util';
+import { emptyFunction, returnEmptyString, setupMoveUpEvents } from '../../../Utils';
+import { Docs, DocUtils } from '../../documents/Documents';
+import { DocumentType } from '../../documents/DocumentTypes';
+import { DragManager } from '../../util/DragManager';
+import { SnappingManager } from '../../util/SnappingManager';
+import { Transform } from '../../util/Transform';
+import { undoBatch } from '../../util/UndoManager';
+import { ContextMenu } from '../ContextMenu';
+import { ContextMenuProps } from '../ContextMenuItem';
+import { EditableView } from '../EditableView';
+import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
+import './CollectionNoteTakingView.scss';
+const higflyout = require('@hig/flyout');
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
 
@@ -39,7 +39,7 @@ interface CSVFieldColumnProps {
     // columnWidth: number;
     numGroupColumns: number;
     gridGap: number;
-    type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined;
+    type: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | undefined;
     headings: () => object[];
     renderChildren: (docs: Doc[]) => JSX.Element[];
     addDocument: (doc: Doc | Doc[]) => boolean;
@@ -48,37 +48,37 @@ interface CSVFieldColumnProps {
     observeHeight: (myref: any) => void;
     unobserveHeight: (myref: any) => void;
     editableViewProps: any;
-    resizeColumns: (n: number) => void
-    columnStartXCoords: number[]
-    PanelWidth: number
-    maxColWidth: number
+    resizeColumns: (n: number) => void;
+    columnStartXCoords: number[];
+    PanelWidth: number;
+    maxColWidth: number;
     // docsByColumnHeader: Map<string, Doc[]>
     // setDocsForColHeader: (key: string, docs: Doc[]) => void
 }
 
 @observer
 export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColumnProps> {
-    @observable private _background = "inherit";
+    @observable private _background = 'inherit';
 
     @computed get columnWidth() {
-      // base cases
-      if (!this.props.columnHeaders || !this.props.headingObject || this.props.columnHeaders.length == 1) {
-        return this.props.maxColWidth
-      }
-      const i = this.props.columnHeaders.indexOf(this.props.headingObject)
-      if (i < 0) {
-        return this.props.maxColWidth
-      }
-      const endColValue = i == this.props.numGroupColumns - 1 ? this.props.PanelWidth : this.props.columnStartXCoords[i+1]
-      // TODO make the math work here. 35 is half of 70, which is the current width of the divider
-      return endColValue - this.props.columnStartXCoords[i] - 30
+        // base cases
+        if (!this.props.columnHeaders || !this.props.headingObject || this.props.columnHeaders.length == 1) {
+            return this.props.maxColWidth;
+        }
+        const i = this.props.columnHeaders.indexOf(this.props.headingObject);
+        if (i < 0) {
+            return this.props.maxColWidth;
+        }
+        const endColValue = i == this.props.numGroupColumns - 1 ? this.props.PanelWidth : this.props.columnStartXCoords[i + 1];
+        // TODO make the math work here. 35 is half of 70, which is the current width of the divider
+        return endColValue - this.props.columnStartXCoords[i] - 30;
     }
 
     private dropDisposer?: DragManager.DragDropDisposer;
     private _headerRef: React.RefObject<HTMLDivElement> = React.createRef();
 
     @observable _heading = this.props.headingObject ? this.props.headingObject.heading : this.props.heading;
-    @observable _color = this.props.headingObject ? this.props.headingObject.color : "#f1efeb";
+    @observable _color = this.props.headingObject ? this.props.headingObject.color : '#f1efeb';
     _ele: HTMLElement | null = null;
 
     // This is likely similar to what we will be doing. Why do we need to make these refs?
@@ -90,7 +90,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
             this.props.observeHeight(ele);
             this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this));
         }
-    }
+    };
 
     componentWillUnmount() {
         this.props.unobserveHeight(this._ele);
@@ -105,10 +105,10 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
     getValue = (value: string): any => {
         const parsed = parseInt(value);
         if (!isNaN(parsed)) return parsed;
-        if (value.toLowerCase().indexOf("true") > -1) return true;
-        if (value.toLowerCase().indexOf("false") > -1) return false;
+        if (value.toLowerCase().indexOf('true') > -1) return true;
+        if (value.toLowerCase().indexOf('false') > -1) return false;
         return value;
-    }
+    };
 
     @action
     headingChanged = (value: string, shiftDown?: boolean) => {
@@ -117,7 +117,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
             if (this.props.columnHeaders?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) {
                 return false;
             }
-            this.props.docList.forEach(d => d[this.props.pivotField] = castedValue);
+            this.props.docList.forEach(d => (d[this.props.pivotField] = castedValue));
             if (this.props.headingObject) {
                 this.props.headingObject.setHeading(castedValue.toString());
                 this._heading = this.props.headingObject.heading;
@@ -125,11 +125,11 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
             return true;
         }
         return false;
-    }
+    };
 
-    @action pointerEntered = () => SnappingManager.GetIsDragging() && (this._background = "#b4b4b4");
-    @action pointerLeave = () => this._background = "inherit";
-    textCallback = (char: string) => this.addNewTextDoc("-typed text-", false, true);
+    @action pointerEntered = () => SnappingManager.GetIsDragging() && (this._background = '#b4b4b4');
+    @action pointerLeave = () => (this._background = 'inherit');
+    textCallback = (char: string) => this.addNewTextDoc('-typed text-', false, true);
 
     @action
     addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => {
@@ -139,46 +139,46 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
         const colValue = this.getValue(this.props.heading);
         newDoc[key] = colValue;
         FormattedTextBox.SelectOnLoad = newDoc[Id];
-        FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? "" : " ";
+        FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? '' : ' ';
         return this.props.addDocument?.(newDoc) || false;
-    }
+    };
 
     @action
     deleteColumn = () => {
         if (!this.props.columnHeaders) {
-          return
+            return;
         }
         if (this.props.headingObject) {
-          const index = this.props.columnHeaders.indexOf(this.props.headingObject);
-          const newIndex = index == 0 ? 1 : index - 1
-          const newHeader = this.props.columnHeaders[newIndex];
-          this.props.docList.forEach(d => d[this.props.pivotField] = newHeader.heading.toString())
-          this.props.columnHeaders.splice(index, 1);
-          this.props.resizeColumns(this.props.columnHeaders.length)
+            const index = this.props.columnHeaders.indexOf(this.props.headingObject);
+            const newIndex = index == 0 ? 1 : index - 1;
+            const newHeader = this.props.columnHeaders[newIndex];
+            this.props.docList.forEach(d => (d[this.props.pivotField] = newHeader.heading.toString()));
+            this.props.columnHeaders.splice(index, 1);
+            this.props.resizeColumns(this.props.columnHeaders.length);
         }
-    }
+    };
 
     headerDown = (e: React.PointerEvent<HTMLDivElement>) => setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction);
 
-    //TODO: I think this is where I'm supposed to edit stuff 
+    //TODO: I think this is where I'm supposed to edit stuff
     startDrag = (e: PointerEvent, down: number[], delta: number[]) => {
-        console.log('in startDrag')
+        console.log('in startDrag');
         // is MakeAlias a way to make a copy of a doc without rendering it?
         const alias = Doc.MakeAlias(this.props.Document);
         // alias._width = this.props.columnWidth / (this.props.columnHeaders?.length || 1);
         alias._width = this.columnWidth;
         alias._pivotField = undefined;
         let value = this.getValue(this._heading);
-        value = typeof value === "string" ? `"${value}"` : value;
+        value = typeof value === 'string' ? `"${value}"` : value;
         alias.viewSpecScript = ScriptField.MakeFunction(`doc.${this.props.pivotField} === ${value}`, { doc: Doc.name });
         if (alias.viewSpecScript) {
-            const options = {hideSource: false}
+            const options = { hideSource: false };
             DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY, options);
-            console.log('in startDrag')
+            console.log('in startDrag');
             return true;
         }
         return false;
-    }
+    };
 
     menuCallback = (x: number, y: number) => {
         ContextMenu.Instance.clearItems();
@@ -187,44 +187,62 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
         const dataDoc = this.props.DataDoc || this.props.Document;
         const pivotValue = this.getValue(this.props.heading);
 
-        DocUtils.addDocumentCreatorMenuItems((doc) => {
-            const key = this.props.pivotField;
-            doc[key] = this.getValue(this.props.heading);
-            FormattedTextBox.SelectOnLoad = doc[Id];
-            return this.props.addDocument?.(doc);
-        }, this.props.addDocument, x, y, true, this.props.pivotField, pivotValue);
+        DocUtils.addDocumentCreatorMenuItems(
+            doc => {
+                const key = this.props.pivotField;
+                doc[key] = this.getValue(this.props.heading);
+                FormattedTextBox.SelectOnLoad = doc[Id];
+                return this.props.addDocument?.(doc);
+            },
+            this.props.addDocument,
+            x,
+            y,
+            true,
+            this.props.pivotField,
+            pivotValue
+        );
 
-        Array.from(Object.keys(Doc.GetProto(dataDoc))).filter(fieldKey => dataDoc[fieldKey] instanceof RichTextField || dataDoc[fieldKey] instanceof ImageField || typeof (dataDoc[fieldKey]) === "string").map(fieldKey =>
-            docItems.push({
-                description: ":" + fieldKey, event: () => {
-                    const created = DocUtils.DocumentFromField(dataDoc, fieldKey, Doc.GetProto(this.props.Document));
-                    if (created) {
-                        if (this.props.Document.isTemplateDoc) {
-                            Doc.MakeMetadataFieldTemplate(created, this.props.Document);
+        Array.from(Object.keys(Doc.GetProto(dataDoc)))
+            .filter(fieldKey => dataDoc[fieldKey] instanceof RichTextField || dataDoc[fieldKey] instanceof ImageField || typeof dataDoc[fieldKey] === 'string')
+            .map(fieldKey =>
+                docItems.push({
+                    description: ':' + fieldKey,
+                    event: () => {
+                        const created = DocUtils.DocumentFromField(dataDoc, fieldKey, Doc.GetProto(this.props.Document));
+                        if (created) {
+                            if (this.props.Document.isTemplateDoc) {
+                                Doc.MakeMetadataFieldTemplate(created, this.props.Document);
+                            }
+                            return this.props.addDocument?.(created);
                         }
-                        return this.props.addDocument?.(created);
-                    }
-                }, icon: "compress-arrows-alt"
-            }));
-        Array.from(Object.keys(Doc.GetProto(dataDoc))).filter(fieldKey => DocListCast(dataDoc[fieldKey]).length).map(fieldKey =>
-            docItems.push({
-                description: ":" + fieldKey, event: () => {
-                    const created = Docs.Create.CarouselDocument([], { _width: 400, _height: 200, title: fieldKey });
-                    if (created) {
-                        const container = this.props.Document.resolvedDataDoc ? Doc.GetProto(this.props.Document) : this.props.Document;
-                        if (container.isTemplateDoc) {
-                            Doc.MakeMetadataFieldTemplate(created, container);
-                            return Doc.AddDocToList(container, Doc.LayoutFieldKey(container), created);
+                    },
+                    icon: 'compress-arrows-alt',
+                })
+            );
+        Array.from(Object.keys(Doc.GetProto(dataDoc)))
+            .filter(fieldKey => DocListCast(dataDoc[fieldKey]).length)
+            .map(fieldKey =>
+                docItems.push({
+                    description: ':' + fieldKey,
+                    event: () => {
+                        const created = Docs.Create.CarouselDocument([], { _width: 400, _height: 200, title: fieldKey });
+                        if (created) {
+                            const container = this.props.Document.resolvedDataDoc ? Doc.GetProto(this.props.Document) : this.props.Document;
+                            if (container.isTemplateDoc) {
+                                Doc.MakeMetadataFieldTemplate(created, container);
+                                return Doc.AddDocToList(container, Doc.LayoutFieldKey(container), created);
+                            }
+                            return this.props.addDocument?.(created) || false;
                         }
-                        return this.props.addDocument?.(created) || false;
-                    }
-                }, icon: "compress-arrows-alt"
-            }));
-        !Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ description: "Doc Fields ...", subitems: docItems, icon: "eye" });
-        !Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ description: "Containers ...", subitems: layoutItems, icon: "eye" });
-        ContextMenu.Instance.setDefaultItem("::", (name: string): void => {
-            Doc.GetProto(this.props.Document)[name] = "";
-            const created = Docs.Create.TextDocument("", { title: name, _width: 250, _autoHeight: true });
+                    },
+                    icon: 'compress-arrows-alt',
+                })
+            );
+        !Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ description: 'Doc Fields ...', subitems: docItems, icon: 'eye' });
+        !Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ description: 'Containers ...', subitems: layoutItems, icon: 'eye' });
+        ContextMenu.Instance.setDefaultItem('::', (name: string): void => {
+            Doc.GetProto(this.props.Document)[name] = '';
+            const created = Docs.Create.TextDocument('', { title: name, _width: 250, _autoHeight: true });
             if (created) {
                 if (this.props.Document.isTemplateDoc) {
                     Doc.MakeMetadataFieldTemplate(created, this.props.Document);
@@ -233,98 +251,100 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
             }
         });
         ContextMenu.Instance.displayMenu(x, y, undefined, true);
-    }
+    };
 
     @computed get innards() {
         TraceMobx();
         const key = this.props.pivotField;
         const heading = this._heading;
         const columnYMargin = this.props.headingObject ? 0 : this.props.yMargin;
-        const evContents = heading ? heading : "25";
-        const headingView = this.props.headingObject ?
-            <div key={heading} className="collectionNoteTakingView-sectionHeader" ref={this._headerRef}
+        const evContents = heading ? heading : '25';
+        const headingView = this.props.headingObject ? (
+            <div
+                key={heading}
+                className="collectionNoteTakingView-sectionHeader"
+                ref={this._headerRef}
                 style={{
                     marginTop: 2 * this.props.yMargin,
                     // width: (this.props.columnWidth) /
                     //     ((uniqueHeadings.length) || 1)
-                    width: this.columnWidth - 20
+                    width: this.columnWidth - 20,
                 }}>
-                <div className="collectionNoteTakingView-sectionHeader-subCont" onPointerDown={this.headerDown}
-                    title={evContents === `No Value` ?
-                        `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ""}
-                    style={{ background: evContents !== `No Value` ? this._color : "inherit" }}>
-                    <EditableView
-                        GetValue={() => evContents}
-                        SetValue={this.headingChanged}
-                        contents={evContents}
-                        oneLine={true}
-                    />
+                <div
+                    className="collectionNoteTakingView-sectionHeader-subCont"
+                    onPointerDown={this.headerDown}
+                    title={evContents === `No Value` ? `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ''}
+                    style={{ background: evContents !== `No Value` ? this._color : 'inherit' }}>
+                    <EditableView GetValue={() => evContents} SetValue={this.headingChanged} contents={evContents} oneLine={true} />
                 </div>
-            </div> : (null);
+            </div>
+        ) : null;
         // const templatecols = `${this.props.columnWidth / this.props.numGroupColumns}px `;
         const templatecols = `${this.columnWidth}px `;
         const type = this.props.Document.type;
-        return <>
-            {headingView}
-            {<div>
-              <div key={`${heading}-stack`} className={`collectionNoteTakingView-Nodes`}
-                  style={{
-                      padding: `${columnYMargin}px ${0}px ${this.props.yMargin}px ${0}px`,
-                      margin: "auto",
-                      width: "max-content", //singleColumn ? undefined : `${cols * (style.columnWidth + style.gridGap) + 2 * style.xMargin - style.gridGap}px`,
-                      height: 'max-content',
-                      position: "relative",
-                      gridGap: this.props.gridGap,
-                      gridTemplateColumns: templatecols,
-                      gridAutoRows: "0px"
-                  }}>
-                  {this.props.renderChildren(this.props.docList)}
-              </div>
+        return (
+            <>
+                {headingView}
+                {
+                    <div>
+                        <div
+                            key={`${heading}-stack`}
+                            className={`collectionNoteTakingView-Nodes`}
+                            style={{
+                                padding: `${columnYMargin}px ${0}px ${this.props.yMargin}px ${0}px`,
+                                margin: 'auto',
+                                width: 'max-content', //singleColumn ? undefined : `${cols * (style.columnWidth + style.gridGap) + 2 * style.xMargin - style.gridGap}px`,
+                                height: 'max-content',
+                                position: 'relative',
+                                gridGap: this.props.gridGap,
+                                gridTemplateColumns: templatecols,
+                                gridAutoRows: '0px',
+                            }}>
+                            {this.props.renderChildren(this.props.docList)}
+                        </div>
 
-              {!this.props.chromeHidden && type !== DocumentType.PRES ?
-                  <div className="collectionNoteTakingView-DocumentButtons"
-                      // style={{ width: this.props.columnWidth / this.props.numGroupColumns, marginBottom: 10 }}>
-                      style={{ width: this.columnWidth - 20, marginBottom: 10 }}>
-                      <div key={`${heading}-add-document`} className="collectionNoteTakingView-addDocumentButton">
-                          <EditableView
-                              GetValue={returnEmptyString}
-                              SetValue={this.addNewTextDoc}
-                              textCallback={this.textCallback}
-                              placeholder={"Type ':' for commands"}
-                              contents={"+ New Node"}
-                              menuCallback={this.menuCallback}
-                          />
-                      </div>
-                      <div key={`${this.props.Document[Id]}-addGroup`} className="collectionNoteTakingView-addDocumentButton">
-                          <EditableView {...this.props.editableViewProps} />
-                      </div>
-                      {(this.props.columnHeaders?.length && this.props.columnHeaders.length > 1) && 
-                          <button className="collectionNoteTakingView-sectionDelete" onClick={this.deleteColumn}>
-                          <FontAwesomeIcon icon="trash" size="lg" />
-                      </button>
-                      }
-                  </div>
-                  : null}
-              </div>
-            }
-        </>;
+                        {!this.props.chromeHidden && type !== DocumentType.PRES ? (
+                            <div
+                                className="collectionNoteTakingView-DocumentButtons"
+                                // style={{ width: this.props.columnWidth / this.props.numGroupColumns, marginBottom: 10 }}>
+                                style={{ width: this.columnWidth - 20, marginBottom: 10 }}>
+                                <div key={`${heading}-add-document`} className="collectionNoteTakingView-addDocumentButton">
+                                    <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} textCallback={this.textCallback} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} />
+                                </div>
+                                <div key={`${this.props.Document[Id]}-addGroup`} className="collectionNoteTakingView-addDocumentButton">
+                                    <EditableView {...this.props.editableViewProps} />
+                                </div>
+                                {this.props.columnHeaders?.length && this.props.columnHeaders.length > 1 && (
+                                    <button className="collectionNoteTakingView-sectionDelete" onClick={this.deleteColumn}>
+                                        <FontAwesomeIcon icon="trash" size="lg" />
+                                    </button>
+                                )}
+                            </div>
+                        ) : null}
+                    </div>
+                }
+            </>
+        );
     }
 
-
     render() {
         TraceMobx();
         const heading = this._heading;
         return (
-            <div className={"collectionNoteTakingViewFieldColumn" + (SnappingManager.GetIsDragging() ? "Dragging" : "")} key={heading}
+            <div
+                className={'collectionNoteTakingViewFieldColumn' + (SnappingManager.GetIsDragging() ? 'Dragging' : '')}
+                key={heading}
                 style={{
-                  //TODO: change this so that it's based on the column width 
+                    //TODO: change this so that it's based on the column width
                     width: this.columnWidth,
-                    height: "100%",
-                    background: this._background
+                    height: '100%',
+                    background: this._background,
                 }}
-                ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}>
+                ref={this.createColumnDropRef}
+                onPointerEnter={this.pointerEntered}
+                onPointerLeave={this.pointerLeave}>
                 {this.innards}
-            </div >
+            </div>
         );
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/collections/CollectionNoteTakingViewDivider.tsx b/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
index ed5dc3715..7d31b3193 100644
--- a/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
@@ -1,61 +1,63 @@
-import { action, observable } from "mobx";
-import * as React from "react";
+import { action, observable } from 'mobx';
+import * as React from 'react';
 
 interface DividerProps {
-  index: number
-  xMargin: number
-  setColumnStartXCoords: (movementX: number, colIndex: number) => void
+    index: number;
+    xMargin: number;
+    setColumnStartXCoords: (movementX: number, colIndex: number) => void;
 }
 
-export default class Divider extends React.Component<DividerProps>{
-  @observable private isHoverActive = false;
-  @observable private isResizingActive = false;
-  
-  @action
-  private registerResizing = (e: React.PointerEvent<HTMLDivElement>) => {
-      e.stopPropagation();
-      e.preventDefault();
-      window.removeEventListener("pointermove", this.onPointerMove);
-      window.removeEventListener("pointerup", this.onPointerUp);
-      window.addEventListener("pointermove", this.onPointerMove);
-      window.addEventListener("pointerup", this.onPointerUp);
-      this.isResizingActive = true;
-  }
+export class CollectionNoteTakingViewDivider extends React.Component<DividerProps> {
+    @observable private isHoverActive = false;
+    @observable private isResizingActive = false;
 
-  @action
-  private onPointerUp = () => {
-      this.isResizingActive = false;
-      this.isHoverActive = false;
-      window.removeEventListener("pointermove", this.onPointerMove);
-      window.removeEventListener("pointerup", this.onPointerUp);
-  }
+    @action
+    private registerResizing = (e: React.PointerEvent<HTMLDivElement>) => {
+        e.stopPropagation();
+        e.preventDefault();
+        window.removeEventListener('pointermove', this.onPointerMove);
+        window.removeEventListener('pointerup', this.onPointerUp);
+        window.addEventListener('pointermove', this.onPointerMove);
+        window.addEventListener('pointerup', this.onPointerUp);
+        this.isResizingActive = true;
+    };
 
-  @action
-  onPointerMove = ({ movementX }: PointerEvent) => {
-    this.props.setColumnStartXCoords(movementX, this.props.index)
-  }
-  
-  render() {
-    return (
-      <div className="columnResizer"
-        style={{
-          display: "flex", 
-          alignItems: "center", 
-          cursor: "col-resize"
-        }}
-        onPointerEnter={action(() => this.isHoverActive = true)}
-        onPointerLeave={action(() => !this.isResizingActive && (this.isHoverActive = false))}
-      >
-        <div className="columnResizer-handler" onPointerDown={e => this.registerResizing(e)}
-          style={{
-            height: "95%",
-            width: 12,
-            borderRight: "4px solid #282828",
-            borderLeft: "4px solid #282828",
-            margin: "0px 10px"
-          }}
-        />
-      </div>
-    )
-  }
-}
\ No newline at end of file
+    @action
+    private onPointerUp = () => {
+        this.isResizingActive = false;
+        this.isHoverActive = false;
+        window.removeEventListener('pointermove', this.onPointerMove);
+        window.removeEventListener('pointerup', this.onPointerUp);
+    };
+
+    @action
+    onPointerMove = ({ movementX }: PointerEvent) => {
+        this.props.setColumnStartXCoords(movementX, this.props.index);
+    };
+
+    render() {
+        return (
+            <div
+                className="columnResizer"
+                style={{
+                    display: 'flex',
+                    alignItems: 'center',
+                    cursor: 'col-resize',
+                }}
+                onPointerEnter={action(() => (this.isHoverActive = true))}
+                onPointerLeave={action(() => !this.isResizingActive && (this.isHoverActive = false))}>
+                <div
+                    className="columnResizer-handler"
+                    onPointerDown={e => this.registerResizing(e)}
+                    style={{
+                        height: '95%',
+                        width: 12,
+                        borderRight: '4px solid #282828',
+                        borderLeft: '4px solid #282828',
+                        margin: '0px 10px',
+                    }}
+                />
+            </div>
+        );
+    }
+}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 1927db51e..ef68cadd7 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -447,8 +447,6 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
                 const newDocs = droppedDocs.length ? droppedDocs : de.complete.docDragData.droppedDocuments; // if nothing was added to the end of the list, then presumably the dropped documents were already in the list, but possibly got reordered so we use them.
 
                 const docs = this.childDocList;
-                // reset drag manager docs, because we just dropped
-                DragManager.docsBeingDragged = [];
                 // still figuring out where to add the document
                 if (docs && newDocs.length) {
                     const insertInd = dropInd === -1 ? docs.length : dropInd + dropAfter;
@@ -456,6 +454,8 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
                     newDocs.filter(ndoc => docs.indexOf(ndoc) !== -1).forEach(ndoc => docs.splice(docs.indexOf(ndoc), 1));
                     docs.splice(insertInd - offset, 0, ...newDocs);
                 }
+                // reset drag manager docs, because we just dropped
+                DragManager.docsBeingDragged.length = 0;
             }
         } else if (de.complete.linkDragData?.dragDocument.context === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) {
             const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _fitWidth: true, title: 'dropped annotation' });
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index afb618b34..1ee1aec5a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -156,9 +156,7 @@ export interface DocumentViewSharedProps {
     scriptContext?: any; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document
     createNewFilterDoc?: () => void;
     updateFilterDoc?: (doc: Doc) => void;
-    // Parker added both of these
-    originalBackgroundColor?: string;
-    isNoteTakingView?: boolean;
+    dontHideOnDrag?: boolean;
 }
 
 // these props are specific to DocuentViews
@@ -494,12 +492,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
     startDragging(x: number, y: number, dropAction: dropActionType, hideSource = false) {
         if (this._mainCont.current) {
             const dragData = new DragManager.DocumentDragData([this.props.Document]);
-            if (this.props.isNoteTakingView) {
-                dragData.draggedDocuments.forEach((doc) => {
-                doc.backgroundColor = "#C9DAEF";
-                doc.opacity = 0.5;
-              });
-            }
             const [left, top] = this.props.ScreenToLocalTransform().scale(this.NativeDimScaling).inverse().transformPoint(0, 0);
             dragData.offset = this.props
                 .ScreenToLocalTransform()
@@ -511,22 +503,16 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
             dragData.treeViewDoc = this.props.treeViewDoc;
             dragData.removeDocument = this.props.removeDocument;
             dragData.moveDocument = this.props.moveDocument;
-            //dragData.dimSource : 
-            // dragEffects field, set dim 
+            //dragData.dimSource :
+            // dragEffects field, set dim
             // add kv pairs to a doc, swap properties with the node while dragging, and then swap when dropping
             // add a dragEffects prop to DocumentView as a function that sets up. Each view has its own prop, when you start dragging:
-            // in Draganager, figure out which doc(s) you're dragging and change what opacity function returns  
+            // in Draganager, figure out which doc(s) you're dragging and change what opacity function returns
             const ffview = this.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
-            ffview && runInAction(() => (ffview.ChildDrag = this.props.DocumentView()));            
-            DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: hideSource || (!dropAction && !this.layoutDoc.onDragStar && !this.props.isNoteTakingView)},
-                () => setTimeout(action(() => {
-                  ffview && (ffview.ChildDrag = undefined)
-                  //TODO: is there a better way than adding another field to the props? Not quite sure how "this" works tbh
-                  if (this.props.isNoteTakingView) {
-                    this.props.Document.backgroundColor = "";
-                    this.props.Document.opacity = 1;
-                  }
-                }))); // this needs to happen after the drop event is processed.
+            ffview && runInAction(() => (ffview.ChildDrag = this.props.DocumentView()));
+            DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: hideSource || (!dropAction && !this.layoutDoc.onDragStart && !this.props.dontHideOnDrag) }, () =>
+                setTimeout(action(() => ffview && (ffview.ChildDrag = undefined)))
+            ); // this needs to happen after the drop event is processed.
             ffview?.setupDragLines(false);
         }
     }
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index b8ee89ef2..add83f4e0 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1001,7 +1001,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
             () => ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, autoHeight: this.autoHeight, marginsHeight: this.autoHeightMargins }),
             ({ sidebarHeight, textHeight, autoHeight, marginsHeight }) => {
                 const newHeight = this.contentScaling * (marginsHeight + Math.max(sidebarHeight, textHeight));
-                autoHeight && newHeight && this.props.setHeight?.(newHeight);
+                if (autoHeight && newHeight && newHeight !== this.rootDoc.height) {
+                    this.props.setHeight?.(newHeight);
+                }
             },
             { fireImmediately: true }
         );
@@ -1695,7 +1697,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
             if (this.props.setHeight && scrollHeight && this.props.renderDepth && !this.props.dontRegisterView) {
                 // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation
                 const setScrollHeight = () => (this.rootDoc[this.fieldKey + '-scrollHeight'] = scrollHeight);
-                if (this.rootDoc === this.layoutDoc.doc || this.layoutDoc.resolvedDataDoc) {
+                if (this.rootDoc === this.layoutDoc || this.layoutDoc.resolvedDataDoc) {
                     setScrollHeight();
                 } else {
                     setTimeout(setScrollHeight, 10); // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template.  So set a timeout and hope its arrived...
-- 
cgit v1.2.3-70-g09d2


From 29d0c334b0bb28b6ae6e1f94fae12d1b4ee0e545 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 3 Aug 2022 18:59:00 -0400
Subject: fixed dragging external documents onto notetaking view

---
 .../collections/CollectionNoteTakingView.scss      | 152 ++++++++++-----------
 .../views/collections/CollectionNoteTakingView.tsx |  66 +++------
 .../collections/CollectionNoteTakingViewColumn.tsx |   3 +-
 3 files changed, 94 insertions(+), 127 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.scss b/src/client/views/collections/CollectionNoteTakingView.scss
index a878033ed..fe98f307e 100644
--- a/src/client/views/collections/CollectionNoteTakingView.scss
+++ b/src/client/views/collections/CollectionNoteTakingView.scss
@@ -1,50 +1,50 @@
-@import "../global/globalCssVariables";
+@import '../global/globalCssVariables';
 
 .collectionNoteTakingView-DocumentButtons {
-  display: flex;
-  justify-content: space-between;
-  margin: auto;
+    display: flex;
+    justify-content: space-between;
+    margin: auto;
 }
 
 .collectionNoteTakingView-addDocumentButton {
-  display: flex;
-  overflow: hidden;
-  margin: auto;
-  width: 100%;
-  overflow: ellipses;
-
-  .editableView-container-editing-oneLine,
-  .editableView-container-editing {
-      color: grey;
-      padding: 10px;
-      width: 100%;
-  }
-
-  .editableView-input:hover,
-  .editableView-container-editing:hover,
-  .editableView-container-editing-oneLine:hover {
-      cursor: text
-  }
-
-  .editableView-input {
-      outline-color: black;
-      letter-spacing: 2px;
-      color: grey;
-      border: 0px;
-      padding: 12px 10px 11px 10px;
-  }
-
-  font-size: 75%;
-  letter-spacing: 2px;
-  cursor: pointer;
-
-  .editableView-input {
-      outline-color: black;
-      letter-spacing: 2px;
-      color: grey;
-      border: 0px;
-      padding: 12px 10px 11px 10px;
-  }
+    display: flex;
+    overflow: hidden;
+    margin: auto;
+    width: 100%;
+    overflow: ellipses;
+
+    .editableView-container-editing-oneLine,
+    .editableView-container-editing {
+        color: grey;
+        padding: 10px;
+        width: 100%;
+    }
+
+    .editableView-input:hover,
+    .editableView-container-editing:hover,
+    .editableView-container-editing-oneLine:hover {
+        cursor: text;
+    }
+
+    .editableView-input {
+        outline-color: black;
+        letter-spacing: 2px;
+        color: grey;
+        border: 0px;
+        padding: 12px 10px 11px 10px;
+    }
+
+    font-size: 75%;
+    letter-spacing: 2px;
+    cursor: pointer;
+
+    .editableView-input {
+        outline-color: black;
+        letter-spacing: 2px;
+        color: grey;
+        border: 0px;
+        padding: 12px 10px 11px 10px;
+    }
 }
 
 .collectionNoteTakingView {
@@ -83,21 +83,13 @@
     overflow-y: auto;
     overflow-x: hidden;
     flex-wrap: wrap;
-    transition: top .5s;
+    transition: top 0.5s;
 
-    >div {
+    > div {
         position: relative;
         display: block;
     }
 
-    .collectionNoteTakingViewFieldColumn {
-        height: max-content;
-    }
-
-    .collectionNoteTakingViewFieldColumnDragging {
-        height: 100%;
-    }
-
     .collectionSchemaView-previewDoc {
         height: 100%;
         position: absolute;
@@ -144,33 +136,33 @@
     // Documents in NoteTaking view
     .collectionNoteTakingView-columnDoc {
         display: flex;
-        // margin: auto; // Removed auto so that it is no longer center aligned - this could be something we change 
+        // margin: auto; // Removed auto so that it is no longer center aligned - this could be something we change
         position: relative;
 
         &:hover {
-          .hoverButtons{
-            opacity: 1;
-          }
+            .hoverButtons {
+                opacity: 1;
+            }
         }
 
         .hoverButtons {
-          display: flex;
-          opacity: 0;
-          position: absolute;
-          height: 100%;
-          left: -35px;
-          justify-content: center;
-          align-items: center;
-          padding: 0px 10px;
-
-          .buttonWrapper {
-            padding: 3px;
-            border-radius: 3px;
-            
-            &:hover {
-              background: rgba(0, 0, 0, 0.26);
+            display: flex;
+            opacity: 0;
+            position: absolute;
+            height: 100%;
+            left: -35px;
+            justify-content: center;
+            align-items: center;
+            padding: 0px 10px;
+
+            .buttonWrapper {
+                padding: 3px;
+                border-radius: 3px;
+
+                &:hover {
+                    background: rgba(0, 0, 0, 0.26);
+                }
             }
-          }
         }
     }
 
@@ -200,7 +192,7 @@
 
         span::before,
         span::after {
-            content: "";
+            content: '';
             width: 50%;
             border-top: dashed gray 1px;
             position: relative;
@@ -241,7 +233,7 @@
         .editableView-input:hover,
         .editableView-container-editing:hover,
         .editableView-container-editing-oneLine:hover {
-            cursor: text
+            cursor: text;
         }
 
         .collectionNoteTakingView-sectionHeader-subCont {
@@ -287,7 +279,7 @@
             height: 100%;
             display: none;
 
-            [class*="css"] {
+            [class*='css'] {
                 max-width: 102px;
             }
 
@@ -329,7 +321,7 @@
             height: 100%;
             display: none;
 
-            [class*="css"] {
+            [class*='css'] {
                 max-width: 102px;
             }
 
@@ -338,7 +330,6 @@
             }
 
             .collectionNoteTakingView-optionPicker {
-
                 .optionOptions {
                     display: inline;
                 }
@@ -398,7 +389,7 @@
         .editableView-input:hover,
         .editableView-container-editing:hover,
         .editableView-container-editing-oneLine:hover {
-            cursor: text
+            cursor: text;
         }
 
         .editableView-input {
@@ -451,7 +442,7 @@
         top: 4px;
         border-radius: 50% 50%;
         background-color: #fff;
-        content: " ";
+        content: ' ';
         cursor: pointer;
         box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26);
         -webkit-transform: scale(1);
@@ -481,7 +472,6 @@
 }
 
 @media only screen and (max-device-width: 480px) {
-
     .collectionNoteTakingView .collectionNoteTakingView-columnDragger,
     .collectionNoteTakingView-columnDragger {
         width: 0.1;
@@ -489,4 +479,4 @@
         opacity: 0;
         font-size: 0;
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 1854a4213..989719c80 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -363,30 +363,30 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
 
     // This function is used to preview where a document will drop in a column once a drag is complete.
     @action
-    onPointerOver = (e: React.PointerEvent) => {
-        if (DragManager.docsBeingDragged.length && this.childDocList) {
+    onPointerOver = (ex: number, ey: number) => {
+        console.log('Pover9ing = ');
+        if (this.childDocList) {
             // get the current docs for the column based on the mouse's x coordinate
             // will use again later, which is why we're saving as local
-            const xCoord = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0] - 2 * this.gridGap;
+            const xCoord = this.props.ScreenToLocalTransform().transformPoint(ex, ey)[0] - 2 * this.gridGap;
             const colDocs = this.getDocsFromXCoord(xCoord);
             // get the index for where you need to insert the doc you are currently dragging
-            const clientY = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[1];
+            const clientY = this.props.ScreenToLocalTransform().transformPoint(ex, ey)[1];
             let dropInd = -1;
             let pos0 = (this.refList.lastElement() as HTMLDivElement).children[0].getBoundingClientRect().height + this.yMargin * 2;
             colDocs.forEach((doc, i) => {
                 let pos1 = this.getDocHeight(doc) + 2 * this.gridGap;
                 pos1 += pos0;
                 // updating drop position based on y coordinates
-                const yCoordInBetween = clientY > pos0 && (clientY < pos1 || i == colDocs.length - 1);
-                if (yCoordInBetween) {
+                const yCoordInBetween = clientY > pos0 && clientY < pos1;
+                if (yCoordInBetween || (clientY < pos0 && i === 0)) {
                     dropInd = i;
-                    // dropAfter = 0;
-                    if (clientY > (pos0 + pos1) / 2) {
-                        // dropAfter = 1;
-                    }
+                } else if (i === colDocs.length - 1 && dropInd === -1) {
+                    dropInd = !colDocs.includes(DragManager.docsBeingDragged.lastElement()) ? i + 1 : i;
                 }
                 pos0 = pos1;
             });
+            console.log('Pover = ' + dropInd + ' ' + this.getColumnFromXCoord(xCoord));
             // 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);
@@ -495,43 +495,20 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     @undoBatch
     @action
     onExternalDrop = async (e: React.DragEvent): Promise<void> => {
-        const where = [e.clientX, e.clientY];
-        let targInd = -1;
-        const docs = this.getDocsFromXCoord(where[0]);
-        docs.map((d, i) => {
-            const pos0 = this.getDocTransform(d)
-                .inverse()
-                .transformPoint(-2 * this.gridGap, -2 * this.gridGap);
-            const pos1 = this.getDocTransform(d).inverse().transformPoint(this.getDocWidth(d), this.getDocHeight(d));
-            // const pos0 = cd.noteTakingDocTransform().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap);
-            // const pos1 = cd.noteTakingDocTransform().inverse().transformPoint(cd.width(), cd.height());
-            if (where[0] > pos0[0] && where[0] < pos1[0] && where[1] > pos0[1] && where[1] < pos1[1]) {
-                targInd = i;
-            }
-        });
-        // this._docXfs.map((cd, i) => {
-        //     const pos = cd.noteTakingDocTransform().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap);
-        //     const pos1 = cd.noteTakingDocTransform().inverse().transformPoint(cd.width(), cd.height());
-        //     if (where[0] > pos[0] && where[0] < pos1[0] && where[1] > pos[1] && where[1] < pos1[1]) {
-        //         targInd = i;
-        //     }
-        // });
-        super.onExternalDrop(e, {}, () => {
-            if (targInd !== -1) {
-                const newDoc = this.childDocs[this.childDocs.length - 1];
-                const docs = this.childDocList;
-                if (docs) {
-                    docs.splice(docs.length - 1, 1);
-                    docs.splice(targInd, 0, newDoc);
-                }
+        const targInd = this.docsDraggedRowCol?.[0] || 0;
+        super.onExternalDrop(e, {}, docus => {
+            this.onPointerOver(e.clientX, e.clientY);
+            docus?.map(doc => this.addDocument(doc));
+            const newDoc = this.childDocs.lastElement();
+            const docs = this.childDocList;
+            if (docs && targInd !== -1) {
+                docs.splice(docs.length - 1, 1);
+                docs.splice(targInd, 0, newDoc);
             }
+            this.removeDocDragHighlight();
         });
     };
 
-    // setDocsForColHeader = (key: string, docs: Doc[]) => {
-    //   this._docsByColumnHeader = new Map(this._docsByColumnHeader.set(key, docs))
-    // }
-
     headings = () => Array.from(this.Sections);
 
     refList: any[] = [];
@@ -723,7 +700,8 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
                         pointerEvents: this.backgroundEvents ? 'all' : undefined,
                     }}
                     onScroll={action(e => (this._scroll = e.currentTarget.scrollTop))}
-                    onPointerOver={this.onPointerOver}
+                    onPointerLeave={action(e => (this.docsDraggedRowCol.length = 0))}
+                    onPointerOver={e => this.onPointerOver(e.clientX, e.clientY)}
                     onDrop={this.onExternalDrop.bind(this)}
                     onContextMenu={this.onContextMenu}
                     onWheel={e => this.props.isContentActive(true) && e.stopPropagation()}>
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 55d032498..5ba262418 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -286,7 +286,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
             <>
                 {headingView}
                 {
-                    <div>
+                    <div style={{ height: '100%' }}>
                         <div
                             key={`${heading}-stack`}
                             className={`collectionNoteTakingView-Nodes`}
@@ -337,7 +337,6 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
                 style={{
                     //TODO: change this so that it's based on the column width
                     width: this.columnWidth,
-                    height: '100%',
                     background: this._background,
                 }}
                 ref={this.createColumnDropRef}
-- 
cgit v1.2.3-70-g09d2


From dbf21b19ecc70047a580023104d05aed0d43c946 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 4 Aug 2022 11:01:37 -0400
Subject: fixed notetaking view to have an 'unset' category for unassigned
 notes.  fixed pivot view to not fail when docs have no width.

---
 .../views/collections/CollectionNoteTakingView.tsx | 30 +++++----
 .../collections/CollectionNoteTakingViewColumn.tsx |  2 +
 .../CollectionFreeFormLayoutEngines.tsx            |  6 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  1 -
 src/client/views/nodes/FilterBox.tsx               |  2 +-
 src/client/views/nodes/FunctionPlotBox.tsx         | 76 ++++++++++++----------
 .../views/nodes/formattedText/RichTextMenu.tsx     | 13 ----
 7 files changed, 66 insertions(+), 64 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 989719c80..f24b98621 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -55,10 +55,18 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         return this.props.chromeHidden || BoolCast(this.layoutDoc.chromeHidden);
     }
     @computed get columnHeaders() {
-        return Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null);
+        const columnHeaders = Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null);
+        let docs = this.childDocs;
+        const needsUnsetCategory = docs.some(d => {
+            return !d[this.notetakingCategoryField] && !columnHeaders.find(sh => sh.heading === 'unset');
+        });
+        if (needsUnsetCategory) {
+            columnHeaders.push(new SchemaHeaderField('unset'));
+        }
+        return columnHeaders;
     }
     @computed get notetakingCategoryField() {
-        return 'noteTakingCategory';
+        return 'NotetakingCategory';
     }
     @computed get filteredChildren() {
         return this.childLayoutPairs.filter(pair => pair.layout instanceof Doc && !pair.layout.hidden).map(pair => pair.layout);
@@ -120,8 +128,8 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     // (2) documentView gets unmounted as you remove it from the list
     get Sections() {
         const columnHeaders = this.columnHeaders;
-        const sections = new Map<SchemaHeaderField, Doc[]>(columnHeaders.map(sh => [sh, []] as [SchemaHeaderField, []]));
         let docs = this.childDocs;
+        const sections = new Map<SchemaHeaderField, Doc[]>(columnHeaders.map(sh => [sh, []] as [SchemaHeaderField, []]));
         const rowCol = this.docsDraggedRowCol;
 
         // filter out the currently dragged docs from the child docs, since we will insert them later
@@ -133,10 +141,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
 
         // this will sort the docs into the correct columns (minus the ones you're currently dragging)
         docs.map(d => {
-            if (!d[this.notetakingCategoryField]) {
-                d[this.notetakingCategoryField] = columnHeaders.length > 0 ? columnHeaders[0].heading : `New Column`;
-            }
-            const sectionValue = d[this.notetakingCategoryField] as object;
+            const sectionValue = (d[this.notetakingCategoryField] as object) ?? `unset`;
 
             // look for if header exists already
             const existingHeader = columnHeaders.find(sh => sh.heading === sectionValue.toString());
@@ -310,7 +315,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     // how to get the width of a document. Currently returns the width of the column (minus margins)
     // if a note doc. Otherwise, returns the normal width (for graphs, images, etc...)
     getDocWidth(d: Doc) {
-        const heading = d[this.notetakingCategoryField] as object;
+        const heading = (d[this.notetakingCategoryField] as object) ?? 'unset';
         const castedSectionValue = heading.toString();
         const existingHeader = this.columnHeaders.find(sh => sh.heading === castedSectionValue);
         const colStartXCoords = this.columnStartXCoords;
@@ -364,7 +369,6 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     // This function is used to preview where a document will drop in a column once a drag is complete.
     @action
     onPointerOver = (ex: number, ey: number) => {
-        console.log('Pover9ing = ');
         if (this.childDocList) {
             // get the current docs for the column based on the mouse's x coordinate
             // will use again later, which is why we're saving as local
@@ -386,7 +390,6 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
                 }
                 pos0 = pos1;
             });
-            console.log('Pover = ' + dropInd + ' ' + this.getColumnFromXCoord(xCoord));
             // 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);
@@ -422,7 +425,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         if (docs) {
             docs.map(d => {
                 if (d instanceof Promise) return;
-                const sectionValue = d[this.notetakingCategoryField] as object;
+                const sectionValue = (d[this.notetakingCategoryField] as object) ?? 'unset';
                 if (sectionValue.toString() == colHeader) {
                     docsMatchingHeader.push(d);
                 }
@@ -619,7 +622,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
             const col = this.sectionNoteTaking(sections[i][0], sections[i][1]);
             eles.push(col);
             if (i < sections.length - 1) {
-                eles.push(<CollectionNoteTakingViewDivider index={i + 1} setColumnStartXCoords={this.setColumnStartXCoords.bind(this)} xMargin={this.xMargin} />);
+                eles.push(<CollectionNoteTakingViewDivider key={`divider${i}`} index={i + 1} setColumnStartXCoords={this.setColumnStartXCoords.bind(this)} xMargin={this.xMargin} />);
             }
         }
         return eles;
@@ -686,7 +689,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         return (
             <>
                 {buttonMenu || noviceExplainer ? (
-                    <div className="documentButtonMenu">
+                    <div className="documentButtonMenu" key="buttons">
                         {buttonMenu ? this.buttonMenu : null}
                         {Doc.UserDoc().noviceMode && noviceExplainer ? <div className="documentExplanation">{noviceExplainer}</div> : null}
                     </div>
@@ -694,6 +697,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
                 <div
                     className="collectionNoteTakingView"
                     ref={this.createRef}
+                    key="notes"
                     style={{
                         overflowY: this.props.isContentActive() ? 'auto' : 'hidden',
                         background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor),
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 5ba262418..8452d895f 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -112,6 +112,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
 
     @action
     headingChanged = (value: string, shiftDown?: boolean) => {
+        console.log('HEADING CH');
         const castedValue = this.getValue(value);
         if (castedValue) {
             if (this.props.columnHeaders?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) {
@@ -255,6 +256,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
 
     @computed get innards() {
         TraceMobx();
+        console.log('INNARD START');
         const key = this.props.pivotField;
         const heading = this._heading;
         const columnYMargin = this.props.headingObject ? 0 : this.props.yMargin;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index a0ebe4cdc..3d85d32a0 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -393,8 +393,10 @@ function normalizeResults(
         0
     );
     aggBounds.r = aggBounds.x + Math.max(minWidth, aggBounds.r - aggBounds.x);
-    const wscale = panelDim[0] / (aggBounds.r - aggBounds.x);
-    let scale = wscale * (aggBounds.b - aggBounds.y) > panelDim[1] ? panelDim[1] / (aggBounds.b - aggBounds.y) : wscale;
+    const width = aggBounds.r - aggBounds.x === 0 ? 1 : aggBounds.r - aggBounds.x;
+    const height = aggBounds.b - aggBounds.y === 0 ? 1 : aggBounds.b - aggBounds.y;
+    const wscale = panelDim[0] / width;
+    let scale = wscale * height > panelDim[1] ? panelDim[1] / height : wscale;
     if (Number.isNaN(scale)) scale = 1;
 
     Array.from(docMap.entries())
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 3e938ec1c..82b377dfa 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -496,7 +496,6 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             const currentCol = DocListCast(this.rootDoc.currentInkDoc);
             const rootDocList = DocListCast(this.rootDoc.data);
             currentCol.push(rootDocList[rootDocList.length - 1]);
-            console.log(currentCol);
 
             this._batch?.end();
         }
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index ff04a293c..dc3fc0396 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -116,7 +116,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @observable _loaded = false;
     componentDidMount() {
         reaction(
-            () => DocListCastAsync(this.layoutDoc.data),
+            () => DocListCastAsync(this.layoutDoc[this.fieldKey]),
             async activeTabsAsync => {
                 const activeTabs = await activeTabsAsync;
                 activeTabs && (await SearchBox.foreachRecursiveDocAsync(activeTabs, emptyFunction));
diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx
index 3ab0a3ff2..15d0f88f6 100644
--- a/src/client/views/nodes/FunctionPlotBox.tsx
+++ b/src/client/views/nodes/FunctionPlotBox.tsx
@@ -1,4 +1,4 @@
-import functionPlot from "function-plot";
+import functionPlot from 'function-plot';
 import { action, computed, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
@@ -12,7 +12,6 @@ import { Docs } from '../../documents/Documents';
 import { ViewBoxBaseComponent } from '../DocComponent';
 import { FieldView, FieldViewProps } from './FieldView';
 
-
 const EquationSchema = createSchema({});
 
 type EquationDocument = makeInterface<[typeof EquationSchema, typeof documentSchema]>;
@@ -20,74 +19,83 @@ const EquationDocument = makeInterface(EquationSchema, documentSchema);
 
 @observer
 export class FunctionPlotBox extends ViewBoxBaseComponent<FieldViewProps>() {
-    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FunctionPlotBox, fieldKey); }
+    public static LayoutString(fieldKey: string) {
+        return FieldView.LayoutString(FunctionPlotBox, fieldKey);
+    }
     public static GraphCount = 0;
     _plot: any;
-    _plotId = "";
+    _plotId = '';
     _plotEle: any;
     constructor(props: any) {
         super(props);
-        this._plotId = "graph" + FunctionPlotBox.GraphCount++;
+        this._plotId = 'graph' + FunctionPlotBox.GraphCount++;
     }
     componentDidMount() {
         this.props.setContentView?.(this);
-        reaction(() => [DocListCast(this.dataDoc.data).lastElement()?.text, this.layoutDoc.width, this.layoutDoc.height, this.dataDoc.xRange, this.dataDoc.yRange],
-            () => this.createGraph());
+        reaction(
+            () => [DocListCast(this.dataDoc[this.fieldKey]).lastElement()?.text, this.layoutDoc.width, this.layoutDoc.height, this.dataDoc.xRange, this.dataDoc.yRange],
+            () => this.createGraph()
+        );
     }
     getAnchor = () => {
         const anchor = Docs.Create.TextanchorDocument({ annotationOn: this.rootDoc });
         anchor.xRange = new List<number>(Array.from(this._plot.options.xAxis.domain));
         anchor.yRange = new List<number>(Array.from(this._plot.options.yAxis.domain));
         return anchor;
-    }
+    };
     @action
     scrollFocus = (doc: Doc, smooth: boolean) => {
-        this.dataDoc.xRange = new List<number>(Array.from(Cast(doc.xRange, listSpec("number"), Cast(this.dataDoc.xRange, listSpec("number"), [-10, 10]))));
-        this.dataDoc.yRange = new List<number>(Array.from(Cast(doc.yRange, listSpec("number"), Cast(this.dataDoc.xRange, listSpec("number"), [-1, 9]))));
+        this.dataDoc.xRange = new List<number>(Array.from(Cast(doc.xRange, listSpec('number'), Cast(this.dataDoc.xRange, listSpec('number'), [-10, 10]))));
+        this.dataDoc.yRange = new List<number>(Array.from(Cast(doc.yRange, listSpec('number'), Cast(this.dataDoc.xRange, listSpec('number'), [-1, 9]))));
         return 0;
-    }
+    };
     createGraph = (ele?: HTMLDivElement) => {
         this._plotEle = ele || this._plotEle;
         const width = this.props.PanelWidth();
         const height = this.props.PanelHeight();
-        const fn = StrCast(DocListCast(this.dataDoc.data).lastElement()?.text, "x^2").replace(/\\frac\{(.*)\}\{(.*)\}/, "($1/$2)");
+        const fn = StrCast(DocListCast(this.dataDoc.data).lastElement()?.text, 'x^2').replace(/\\frac\{(.*)\}\{(.*)\}/, '($1/$2)');
         try {
             this._plot = functionPlot({
-                target: "#" + this._plotEle.id,
+                target: '#' + this._plotEle.id,
                 width,
                 height,
-                xAxis: { domain: Cast(this.dataDoc.xRange, listSpec("number"), [-10, 10]) },
-                yAxis: { domain: Cast(this.dataDoc.xRange, listSpec("number"), [-1, 9]) },
+                xAxis: { domain: Cast(this.dataDoc.xRange, listSpec('number'), [-10, 10]) },
+                yAxis: { domain: Cast(this.dataDoc.xRange, listSpec('number'), [-1, 9]) },
                 grid: true,
                 data: [
                     {
                         fn,
                         // derivative: { fn: "2 * x", updateOnMouseMove: true }
-                    }
-                ]
+                    },
+                ],
             });
         } catch (e) {
             console.log(e);
         }
-    }
+    };
     @computed get theGraph() {
-        return <div id={`${this._plotId}`} ref={r => r && this.createGraph(r)} style={{ position: "absolute", width: "100%", height: "100%" }}
-            onPointerDown={e => e.stopPropagation()} />;
+        return <div id={`${this._plotId}`} ref={r => r && this.createGraph(r)} style={{ position: 'absolute', width: '100%', height: '100%' }} onPointerDown={e => e.stopPropagation()} />;
     }
     render() {
         TraceMobx();
-        return (<div
-            style={{
-                pointerEvents: !this.isContentActive() ? "all" : undefined,
-                width: this.props.PanelWidth(),
-                height: this.props.PanelHeight()
-            }}
-        >
-            {this.theGraph}
-            <div style={{
-                display: this.props.isSelected() ? "none" : undefined, position: "absolute", width: "100%", height: "100%",
-                pointerEvents: "all"
-            }} />
-        </div>);
+        return (
+            <div
+                style={{
+                    pointerEvents: !this.isContentActive() ? 'all' : undefined,
+                    width: this.props.PanelWidth(),
+                    height: this.props.PanelHeight(),
+                }}>
+                {this.theGraph}
+                <div
+                    style={{
+                        display: this.props.isSelected() ? 'none' : undefined,
+                        position: 'absolute',
+                        width: '100%',
+                        height: '100%',
+                        pointerEvents: 'all',
+                    }}
+                />
+            </div>
+        );
     }
-}
\ No newline at end of file
+}
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 21326efaa..2a77210ae 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -60,7 +60,6 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
     @observable private showLinkDropdown: boolean = false;
 
     _reaction: IReactionDisposer | undefined;
-    _delayHide = false;
     constructor(props: Readonly<{}>) {
         super(props);
         runInAction(() => {
@@ -70,16 +69,6 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
         });
     }
 
-    componentDidMount() {
-        this._reaction = reaction(
-            () => SelectionManager.Views(),
-            () => this._delayHide && !(this._delayHide = false) && this.fadeOut(true)
-        );
-    }
-    componentWillUnmount() {
-        this._reaction?.();
-    }
-
     @computed get noAutoLink() {
         return this._noLinkActive;
     }
@@ -108,8 +97,6 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
         return this._activeAlignment;
     }
 
-    public delayHide = () => (this._delayHide = true);
-
     @action
     public updateMenu(view: EditorView | undefined, lastState: EditorState | undefined, props: any) {
         if (this._linkToRef.current?.getBoundingClientRect().width) {
-- 
cgit v1.2.3-70-g09d2


From abdbf5c657b9d1d9a26a4d46dda2097be152f4ff Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 4 Aug 2022 17:03:21 -0400
Subject: fixed undo/redo for notetaking view.   fixed list undo/redo for
 schemaheaderfields -- not very elegant though.

---
 .../views/collections/CollectionNoteTakingView.tsx | 52 ++++++++--------
 .../collections/CollectionNoteTakingViewColumn.tsx | 39 ++----------
 src/fields/List.ts                                 | 72 ++++++++++++----------
 src/fields/util.ts                                 | 12 +++-
 4 files changed, 80 insertions(+), 95 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index f24b98621..1bf5b7d86 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -42,12 +42,10 @@ export type collectionNoteTakingViewProps = {
 
 @observer
 export class CollectionNoteTakingView extends CollectionSubView<Partial<collectionNoteTakingViewProps>>() {
-    _autoHeightDisposer?: IReactionDisposer;
+    _disposers: { [key: string]: IReactionDisposer } = {};
     _masonryGridRef: HTMLDivElement | null = null;
     _draggerRef = React.createRef<HTMLDivElement>();
-    // _docXfs: { height: () => number, width: () => number, noteTakingDocTransform: () => Transform }[] = [];
-    // @observable _docsByColumnHeader = new Map<string, Doc[]>();
-    //TODO: need to make sure that we save the mapping
+    @observable columnStartXCoords: number[] = [];
     @observable docsDraggedRowCol: number[] = [];
     @observable _cursor: CursorProperty = 'grab';
     @observable _scroll = 0; // used to force the document decoration to update when scrolling
@@ -86,7 +84,6 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     @computed get numGroupColumns() {
         return this.columnHeaders.length;
     }
-    @observable columnStartXCoords: number[] = [];
     @computed get PanelWidth() {
         return this.props.PanelWidth();
     }
@@ -100,11 +97,9 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         super(props);
         if (this.columnHeaders === undefined) {
             this.dataDoc.columnHeaders = new List<SchemaHeaderField>([new SchemaHeaderField('New Column')]);
-            this.columnStartXCoords = [0];
             // add all of the docs that have not been added to a column to this new column
         } else {
-            const numHeaders = this.columnHeaders.length;
-            this.resizeColumns(numHeaders);
+            this.resizeColumns(this.columnHeaders.length);
         }
     }
 
@@ -126,7 +121,8 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
 
     // [CAVEATS] (1) keep track of the offsetting
     // (2) documentView gets unmounted as you remove it from the list
-    get Sections() {
+    @computed get Sections() {
+        TraceMobx();
         const columnHeaders = this.columnHeaders;
         let docs = this.childDocs;
         const sections = new Map<SchemaHeaderField, Doc[]>(columnHeaders.map(sh => [sh, []] as [SchemaHeaderField, []]));
@@ -169,16 +165,21 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     componentDidMount() {
         super.componentDidMount?.();
         document.addEventListener('pointerup', this.removeDocDragHighlight, true);
-        this._autoHeightDisposer = reaction(
+        this._disposers.autoHeight = reaction(
             () => this.layoutDoc._autoHeight,
             autoHeight => autoHeight && this.props.setHeight?.(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), this.headerMargin + Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', ''))))))
         );
+        this._disposers.headers = reaction(
+            () => this.columnHeaders.slice(),
+            headers => this.resizeColumns(headers.length),
+            { fireImmediately: true }
+        );
     }
 
     componentWillUnmount() {
         document.removeEventListener('pointerup', this.removeDocDragHighlight, true);
         super.componentWillUnmount();
-        this._autoHeightDisposer?.();
+        Object.keys(this._disposers).forEach(key => this._disposers[key]());
     }
 
     @action
@@ -315,9 +316,8 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     // how to get the width of a document. Currently returns the width of the column (minus margins)
     // if a note doc. Otherwise, returns the normal width (for graphs, images, etc...)
     getDocWidth(d: Doc) {
-        const heading = (d[this.notetakingCategoryField] as object) ?? 'unset';
-        const castedSectionValue = heading.toString();
-        const existingHeader = this.columnHeaders.find(sh => sh.heading === castedSectionValue);
+        const heading = StrCast(d[this.notetakingCategoryField], 'unset');
+        const existingHeader = this.columnHeaders.find(sh => sh.heading === heading);
         const colStartXCoords = this.columnStartXCoords;
         if (!existingHeader) {
             return 1000;
@@ -352,6 +352,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     }
 
     // called when a column is either added or deleted. This function creates n evenly spaced columns
+    @action
     resizeColumns = (n: number) => {
         const totalWidth = this.PanelWidth;
         const dividerWidth = 32;
@@ -368,8 +369,8 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
 
     // This function is used to preview where a document will drop in a column once a drag is complete.
     @action
-    onPointerOver = (ex: number, ey: number) => {
-        if (this.childDocList) {
+    onPointerOver = (buttons: boolean, ex: number, ey: number) => {
+        if (this.childDocList && buttons) {
             // get the current docs for the column based on the mouse's x coordinate
             // will use again later, which is why we're saving as local
             const xCoord = this.props.ScreenToLocalTransform().transformPoint(ex, ey)[0] - 2 * this.gridGap;
@@ -500,7 +501,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     onExternalDrop = async (e: React.DragEvent): Promise<void> => {
         const targInd = this.docsDraggedRowCol?.[0] || 0;
         super.onExternalDrop(e, {}, docus => {
-            this.onPointerOver(e.clientX, e.clientY);
+            this.onPointerOver(true, e.clientX, e.clientY);
             docus?.map(doc => this.addDocument(doc));
             const newDoc = this.childDocs.lastElement();
             const docs = this.childDocList;
@@ -515,6 +516,11 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     headings = () => Array.from(this.Sections);
 
     refList: any[] = [];
+    editableViewProps = () => ({
+        GetValue: () => '',
+        SetValue: this.addGroup,
+        contents: '+ New Column',
+    });
 
     sectionNoteTaking = (heading: SchemaHeaderField | undefined, docList: Doc[]) => {
         const type = 'number';
@@ -544,7 +550,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
                 columnHeaders={this.columnHeaders}
                 Document={this.props.Document}
                 DataDoc={this.props.DataDoc}
-                resizeColumns={this.resizeColumns.bind(this)}
+                resizeColumns={this.resizeColumns}
                 renderChildren={this.children}
                 numGroupColumns={this.numGroupColumns}
                 gridGap={this.gridGap}
@@ -561,11 +567,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
                 type={type}
                 createDropTarget={this.createDashEventsTarget}
                 screenToLocalTransform={this.props.ScreenToLocalTransform}
-                editableViewProps={{
-                    GetValue: () => '',
-                    SetValue: this.addGroup,
-                    contents: '+ New Column',
-                }}
+                editableViewProps={this.editableViewProps}
             />
         );
     };
@@ -622,7 +624,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
             const col = this.sectionNoteTaking(sections[i][0], sections[i][1]);
             eles.push(col);
             if (i < sections.length - 1) {
-                eles.push(<CollectionNoteTakingViewDivider key={`divider${i}`} index={i + 1} setColumnStartXCoords={this.setColumnStartXCoords.bind(this)} xMargin={this.xMargin} />);
+                eles.push(<CollectionNoteTakingViewDivider key={`divider${i}`} index={i + 1} setColumnStartXCoords={this.setColumnStartXCoords} xMargin={this.xMargin} />);
             }
         }
         return eles;
@@ -705,7 +707,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
                     }}
                     onScroll={action(e => (this._scroll = e.currentTarget.scrollTop))}
                     onPointerLeave={action(e => (this.docsDraggedRowCol.length = 0))}
-                    onPointerOver={e => this.onPointerOver(e.clientX, e.clientY)}
+                    onPointerOver={e => this.onPointerOver(e.buttons ? true : false, e.clientX, e.clientY)}
                     onDrop={this.onExternalDrop.bind(this)}
                     onContextMenu={this.onContextMenu}
                     onWheel={e => this.props.isContentActive(true) && e.stopPropagation()}>
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 8452d895f..9b7518c60 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -47,7 +47,7 @@ interface CSVFieldColumnProps {
     screenToLocalTransform: () => Transform;
     observeHeight: (myref: any) => void;
     unobserveHeight: (myref: any) => void;
-    editableViewProps: any;
+    editableViewProps: () => any;
     resizeColumns: (n: number) => void;
     columnStartXCoords: number[];
     PanelWidth: number;
@@ -112,7 +112,6 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
 
     @action
     headingChanged = (value: string, shiftDown?: boolean) => {
-        console.log('HEADING CH');
         const castedValue = this.getValue(value);
         if (castedValue) {
             if (this.props.columnHeaders?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) {
@@ -144,43 +143,17 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
         return this.props.addDocument?.(newDoc) || false;
     };
 
+    @undoBatch
     @action
     deleteColumn = () => {
-        if (!this.props.columnHeaders) {
-            return;
-        }
-        if (this.props.headingObject) {
+        if (this.props.columnHeaders && this.props.headingObject) {
             const index = this.props.columnHeaders.indexOf(this.props.headingObject);
-            const newIndex = index == 0 ? 1 : index - 1;
-            const newHeader = this.props.columnHeaders[newIndex];
-            this.props.docList.forEach(d => (d[this.props.pivotField] = newHeader.heading.toString()));
+            this.props.docList.forEach(d => (d[this.props.pivotField] = 'unset'));
             this.props.columnHeaders.splice(index, 1);
             this.props.resizeColumns(this.props.columnHeaders.length);
         }
     };
 
-    headerDown = (e: React.PointerEvent<HTMLDivElement>) => setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction);
-
-    //TODO: I think this is where I'm supposed to edit stuff
-    startDrag = (e: PointerEvent, down: number[], delta: number[]) => {
-        console.log('in startDrag');
-        // is MakeAlias a way to make a copy of a doc without rendering it?
-        const alias = Doc.MakeAlias(this.props.Document);
-        // alias._width = this.props.columnWidth / (this.props.columnHeaders?.length || 1);
-        alias._width = this.columnWidth;
-        alias._pivotField = undefined;
-        let value = this.getValue(this._heading);
-        value = typeof value === 'string' ? `"${value}"` : value;
-        alias.viewSpecScript = ScriptField.MakeFunction(`doc.${this.props.pivotField} === ${value}`, { doc: Doc.name });
-        if (alias.viewSpecScript) {
-            const options = { hideSource: false };
-            DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY, options);
-            console.log('in startDrag');
-            return true;
-        }
-        return false;
-    };
-
     menuCallback = (x: number, y: number) => {
         ContextMenu.Instance.clearItems();
         const layoutItems: ContextMenuProps[] = [];
@@ -256,7 +229,6 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
 
     @computed get innards() {
         TraceMobx();
-        console.log('INNARD START');
         const key = this.props.pivotField;
         const heading = this._heading;
         const columnYMargin = this.props.headingObject ? 0 : this.props.yMargin;
@@ -274,7 +246,6 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
                 }}>
                 <div
                     className="collectionNoteTakingView-sectionHeader-subCont"
-                    onPointerDown={this.headerDown}
                     title={evContents === `No Value` ? `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ''}
                     style={{ background: evContents !== `No Value` ? this._color : 'inherit' }}>
                     <EditableView GetValue={() => evContents} SetValue={this.headingChanged} contents={evContents} oneLine={true} />
@@ -314,7 +285,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
                                     <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} textCallback={this.textCallback} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} />
                                 </div>
                                 <div key={`${this.props.Document[Id]}-addGroup`} className="collectionNoteTakingView-addDocumentButton">
-                                    <EditableView {...this.props.editableViewProps} />
+                                    <EditableView {...this.props.editableViewProps()} />
                                 </div>
                                 {this.props.columnHeaders?.length && this.props.columnHeaders.length > 1 && (
                                     <button className="collectionNoteTakingView-sectionDelete" onClick={this.deleteColumn}>
diff --git a/src/fields/List.ts b/src/fields/List.ts
index b15548327..5cc4ca543 100644
--- a/src/fields/List.ts
+++ b/src/fields/List.ts
@@ -1,25 +1,25 @@
-import { action, observable } from "mobx";
-import { alias, list, serializable } from "serializr";
-import { DocServer } from "../client/DocServer";
-import { ScriptingGlobals } from "../client/util/ScriptingGlobals";
-import { afterDocDeserialize, autoObject, Deserializable } from "../client/util/SerializationHelper";
-import { Field } from "./Doc";
-import { Copy, OnUpdate, Parent, Self, SelfProxy, ToScriptString, ToString, Update } from "./FieldSymbols";
-import { ObjectField } from "./ObjectField";
-import { ProxyField } from "./Proxy";
-import { RefField } from "./RefField";
-import { listSpec } from "./Schema";
-import { Cast } from "./Types";
-import { deleteProperty, getter, setter, updateFunction } from "./util";
+import { action, observable } from 'mobx';
+import { alias, list, serializable } from 'serializr';
+import { DocServer } from '../client/DocServer';
+import { ScriptingGlobals } from '../client/util/ScriptingGlobals';
+import { afterDocDeserialize, autoObject, Deserializable } from '../client/util/SerializationHelper';
+import { Field } from './Doc';
+import { Copy, OnUpdate, Parent, Self, SelfProxy, ToScriptString, ToString, Update } from './FieldSymbols';
+import { ObjectField } from './ObjectField';
+import { ProxyField } from './Proxy';
+import { RefField } from './RefField';
+import { listSpec } from './Schema';
+import { Cast } from './Types';
+import { deleteProperty, getter, setter, updateFunction } from './util';
 
 const listHandlers: any = {
     /// Mutator methods
     copyWithin() {
-        throw new Error("copyWithin not supported yet");
+        throw new Error('copyWithin not supported yet');
     },
     fill(value: any, start?: number, end?: number) {
         if (value instanceof RefField) {
-            throw new Error("fill with RefFields not supported yet");
+            throw new Error('fill with RefFields not supported yet');
         }
         const res = this[Self].__fields.fill(value, start, end);
         this[Update]();
@@ -44,7 +44,7 @@ const listHandlers: any = {
             }
         }
         const res = list.__fields.push(...items);
-        this[Update]({ op: "$addToSet", items, length: length + items.length });
+        this[Update]({ op: '$addToSet', items, length: length + items.length });
         return res;
     }),
     reverse() {
@@ -78,8 +78,13 @@ const listHandlers: any = {
             }
         }
         const res = list.__fields.splice(start, deleteCount, ...items);
-        this[Update](items.length === 0 && deleteCount ? { op: "$remFromSet", items: removed, length: list.__fields.length } :
-            items.length && !deleteCount && start === list.__fields.length ? { op: "$addToSet", items, length: list.__fields.length } : undefined);
+        this[Update](
+            items.length === 0 && deleteCount
+                ? { op: '$remFromSet', items: removed, length: list.__fields.length }
+                : items.length && !deleteCount && start === list.__fields.length
+                ? { op: '$addToSet', items, length: list.__fields.length }
+                : undefined
+        );
         return res.map(toRealField);
     }),
     unshift(...items: any[]) {
@@ -98,7 +103,6 @@ const listHandlers: any = {
         const res = this[Self].__fields.unshift(...items);
         this[Update]();
         return res;
-
     },
     /// Accessor methods
     concat: action(function (this: any, ...items: any[]) {
@@ -198,7 +202,7 @@ const listHandlers: any = {
     },
     [Symbol.iterator]() {
         return this[Self].__realFields().values();
-    }
+    },
 };
 
 function toObjectField(field: Field) {
@@ -217,14 +221,14 @@ function listGetter(target: any, prop: string | number | symbol, receiver: any):
 }
 
 interface ListSpliceUpdate<T> {
-    type: "splice";
+    type: 'splice';
     index: number;
     added: T[];
     removedCount: number;
 }
 
 interface ListIndexUpdate<T> {
-    type: "update";
+    type: 'update';
     index: number;
     newValue: T;
 }
@@ -233,7 +237,7 @@ type ListUpdate<T> = ListSpliceUpdate<T> | ListIndexUpdate<T>;
 
 type StoredType<T extends Field> = T extends RefField ? ProxyField<T> : T;
 
-@Deserializable("list")
+@Deserializable('list')
 class ListImpl<T extends Field> extends ObjectField {
     constructor(fields?: T[]) {
         super();
@@ -244,14 +248,16 @@ class ListImpl<T extends Field> extends ObjectField {
             getOwnPropertyDescriptor: (target, prop) => {
                 if (prop in target.__fields) {
                     return {
-                        configurable: true,//TODO Should configurable be true?
+                        configurable: true, //TODO Should configurable be true?
                         enumerable: true,
                     };
                 }
                 return Reflect.getOwnPropertyDescriptor(target, prop);
             },
             deleteProperty: deleteProperty,
-            defineProperty: () => { throw new Error("Currently properties can't be defined on documents using Object.defineProperty"); },
+            defineProperty: () => {
+                throw new Error("Currently properties can't be defined on documents using Object.defineProperty");
+            },
         });
         this[SelfProxy] = list;
         if (fields) {
@@ -265,7 +271,7 @@ class ListImpl<T extends Field> extends ObjectField {
     // this requests all ProxyFields at the same time to avoid the overhead
     // of separate network requests and separate updates to the React dom.
     private __realFields() {
-        const promised = this.__fields.filter(f => f instanceof ProxyField && f.promisedValue()).map(f => ({ field: f as any, promisedFieldId: (f instanceof ProxyField) ? f.promisedValue() : "" }));
+        const promised = this.__fields.filter(f => f instanceof ProxyField && f.promisedValue()).map(f => ({ field: f as any, promisedFieldId: f instanceof ProxyField ? f.promisedValue() : '' }));
         // if we find any ProxyFields that don't have a current value, then
         // start the server request for all of them
         if (promised.length) {
@@ -282,7 +288,7 @@ class ListImpl<T extends Field> extends ObjectField {
         return this.__fields.map(toRealField);
     }
 
-    @serializable(alias("fields", list(autoObject(), { afterDeserialize: afterDocDeserialize })))
+    @serializable(alias('fields', list(autoObject(), { afterDeserialize: afterDocDeserialize })))
     private get __fields() {
         return this.___fields;
     }
@@ -299,7 +305,7 @@ class ListImpl<T extends Field> extends ObjectField {
     }
 
     [Copy]() {
-        const copiedData = this[Self].__fields.map(f => f instanceof ObjectField ? f[Copy]() : f);
+        const copiedData = this[Self].__fields.map(f => (f instanceof ObjectField ? f[Copy]() : f));
         const deepCopy = new ListImpl<T>(copiedData as any);
         return deepCopy;
     }
@@ -313,7 +319,7 @@ class ListImpl<T extends Field> extends ObjectField {
         const update = this[OnUpdate];
         // update && update(diff);
         update?.(diff);
-    }
+    };
 
     private [Self] = this;
     private [SelfProxy]: any;
@@ -328,9 +334,9 @@ class ListImpl<T extends Field> extends ObjectField {
 export type List<T extends Field> = ListImpl<T> & (T | (T extends RefField ? Promise<T> : never))[];
 export const List: { new <T extends Field>(fields?: T[]): List<T> } = ListImpl as any;
 
-ScriptingGlobals.add("List", List);
+ScriptingGlobals.add('List', List);
 ScriptingGlobals.add(function compareLists(l1: any, l2: any) {
-    const L1 = Cast(l1, listSpec("string"), []);
-    const L2 = Cast(l2, listSpec("string"), []);
+    const L1 = Cast(l1, listSpec('string'), []);
+    const L2 = Cast(l2, listSpec('string'), []);
     return !L1 && !L2 ? true : L1 && L2 && L1.length === L2.length && L2.reduce((p, v) => p && L1.includes(v), true);
-}, "compare two lists");
\ No newline at end of file
+}, 'compare two lists');
diff --git a/src/fields/util.ts b/src/fields/util.ts
index 41e723119..d87bb6656 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -33,6 +33,7 @@ import { ObjectField } from './ObjectField';
 import { PrefetchProxy, ProxyField } from './Proxy';
 import { RefField } from './RefField';
 import { RichTextField } from './RichTextField';
+import { SchemaHeaderField } from './SchemaHeaderField';
 import { ComputedField } from './ScriptField';
 import { ScriptCast, StrCast } from './Types';
 
@@ -455,7 +456,7 @@ export function updateFunction(target: any, prop: any, value: any, receiver: any
                         ? {
                               redo: action(() => {
                                   diff.items.forEach((item: any) => {
-                                      const ind = receiver[prop].indexOf(item.value ? item.value() : item);
+                                      const ind = item instanceof SchemaHeaderField ? receiver[prop].findIndex((ele: any) => ele instanceof SchemaHeaderField && ele.heading === item.heading) : receiver[prop].indexOf(item.value ? item.value() : item);
                                       ind !== -1 && receiver[prop].splice(ind, 1);
                                   });
                                   lastValue = ObjectField.MakeCopy(receiver[prop]);
@@ -463,8 +464,13 @@ export function updateFunction(target: any, prop: any, value: any, receiver: any
                               undo: () => {
                                   // console.log("undo $rem: " + prop, diff.items) // bcz: uncomment to log undo
                                   diff.items.forEach((item: any) => {
-                                      const ind = (prevValue as List<any>).indexOf(item.value ? item.value() : item);
-                                      ind !== -1 && receiver[prop].indexOf(item.value ? item.value() : item) === -1 && receiver[prop].splice(ind, 0, item);
+                                      if (item instanceof SchemaHeaderField) {
+                                          const ind = (prevValue as List<any>).findIndex((ele: any) => ele instanceof SchemaHeaderField && ele.heading === item.heading);
+                                          ind !== -1 && receiver[prop].findIndex((ele: any) => ele instanceof SchemaHeaderField && ele.heading === item.heading) === -1 && receiver[prop].splice(ind, 0, item);
+                                      } else {
+                                          const ind = (prevValue as List<any>).indexOf(item.value ? item.value() : item);
+                                          ind !== -1 && receiver[prop].indexOf(item.value ? item.value() : item) === -1 && receiver[prop].splice(ind, 0, item);
+                                      }
                                   });
                                   lastValue = ObjectField.MakeCopy(receiver[prop]);
                               },
-- 
cgit v1.2.3-70-g09d2


From 1638527259a072dfc2ab286bd27bbb1751e8434e Mon Sep 17 00:00:00 2001
From: ljungster <parkerljung@gmail.com>
Date: Fri, 5 Aug 2022 08:30:35 -0500
Subject: stashing to look at master

---
 .../views/collections/CollectionNoteTakingView.tsx | 27 ++++++++++++++++++++--
 .../collections/CollectionNoteTakingViewColumn.tsx |  4 ++++
 2 files changed, 29 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 9519e9aaa..3e2b8b762 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -74,7 +74,8 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
           this.layoutDoc._columnHeaders = new List<SchemaHeaderField>([new SchemaHeaderField('New Column')]);
           this.columnStartXCoords = [0]
           // add all of the docs that have not been added to a column to this new column
-        } else {
+        } 
+        else {
           const numHeaders = this.columnHeaders.length
           this.resizeColumns(numHeaders)
         }
@@ -457,6 +458,27 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         return true;
     }
 
+    // Used in CollectionNoteTakingView to delete a column when the user clicks the delete button
+    // @action
+    // @undoBatch
+    // deleteColumn = (headingObject: SchemaHeaderField | undefined, docList: Doc[]) => {
+    //     if (!this.columnHeaders) {
+    //       return
+    //     }
+    //     if (headingObject) {
+    //       const index = this.columnHeaders.indexOf(headingObject);
+    //       const newIndex = index == 0 ? 1 : index - 1
+    //       const newHeader = this.columnHeaders[newIndex];
+    //       docList.forEach(d => d[this.pivotField] = newHeader.heading.toString())
+    //       // this.props.columnHeaders.splice(index, 1);
+    //       const newHeaders = this.columnHeaders;
+    //       newHeaders.splice(index, 1);
+    //       const test = this.layoutDoc._columnHeaders;
+    //       this.columnHeaders = newHeaders;
+    //       this.resizeColumns(newHeaders.length)
+    //     }
+    // }
+
     // when dropping outside of the current noteTaking context (like a new tab, freeform view, etc...)
     @undoBatch
     @action
@@ -554,12 +576,13 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
 
     // called when adding a new columnHeader
     @action
+    @undoBatch
     addGroup = (value: string) => {
         if (value && this.columnHeaders) {
-            this.resizeColumns(this.columnHeaders.length + 1)
             const schemaHdrField = new SchemaHeaderField(value);
             this.columnHeaders.push(schemaHdrField);
             DocUtils.addFieldEnumerations(undefined, this.pivotField, [{ title: value, _backgroundColor: "schemaHdrField.color" }]);
+            this.resizeColumns(this.columnHeaders.length + 1)
             return true;
         }
         return false;
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index bdcb9c399..0ee5985bb 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -144,6 +144,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
     }
 
     @action
+    @undoBatch
     deleteColumn = () => {
         if (!this.props.columnHeaders) {
           return
@@ -154,6 +155,9 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
           const newHeader = this.props.columnHeaders[newIndex];
           this.props.docList.forEach(d => d[this.props.pivotField] = newHeader.heading.toString())
           this.props.columnHeaders.splice(index, 1);
+          // const newHeaders = this.props.columnHeaders;
+          // newHeaders.splice(index, 1);
+          // this.props.columnHeaders = newHeaders;
           this.props.resizeColumns(this.props.columnHeaders.length)
         }
     }
-- 
cgit v1.2.3-70-g09d2


From 7b7374c4b20a0488c74b49cdc50daa6867dce2a9 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 5 Aug 2022 10:51:55 -0400
Subject: fixed undo of adding column in notetaking view

---
 .../views/collections/CollectionNoteTakingView.tsx | 25 +++++++++++++++++-----
 .../collections/CollectionNoteTakingViewColumn.tsx |  1 +
 2 files changed, 21 insertions(+), 5 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index e0c79a265..c07473ee1 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -44,8 +44,8 @@ export type collectionNoteTakingViewProps = {
 export class CollectionNoteTakingView extends CollectionSubView<Partial<collectionNoteTakingViewProps>>() {
     _disposers: { [key: string]: IReactionDisposer } = {};
     _masonryGridRef: HTMLDivElement | null = null;
-    _draggerRef = React.createRef<HTMLDivElement>();
-    @observable columnStartXCoords: number[] = [];
+    _draggerRef = React.createRef<HTMLDivElement>(); // change to relative widths for deleting.  change storage from columnStartXCoords to columnHeaders (schemaHeaderFields has a widgth alrady)
+    @observable columnStartXCoords: number[] = []; // columnHeaders -- SchemaHeaderField -- widht
     @observable docsDraggedRowCol: number[] = [];
     @observable _cursor: CursorProperty = 'grab';
     @observable _scroll = 0; // used to force the document decoration to update when scrolling
@@ -58,6 +58,22 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         const needsUnsetCategory = docs.some(d => {
             return !d[this.notetakingCategoryField] && !columnHeaders.find(sh => sh.heading === 'unset');
         });
+
+        //  @#Oberable draggedColIndex = ...
+        //@observable cloneDivXYcoords
+        // @observable clonedDiv...
+
+        // render() {
+        //    { this.clonedDiv ? <div clone styule={{transform: clonedDivXYCoords}} : null}
+        // }
+
+        //  in NoteatakinView Column code, add a poinerDown handler that calls setupMoveUpEvents() which will clone the column div
+        //    and re-render it under the cursor during move events.
+        //    that move move event will update 2 observales -- the draggedColIndex up above, and the location of the clonedDiv so that the render in this view will know where to render the cloned div
+        // add observable variable that tells drag column to rnder in a different location than where the schemaHeaderFiel sa y ot.
+        // if (col 1 is where col 3) {
+        //     return 3 2 1 4 56
+        // }
         if (needsUnsetCategory) {
             columnHeaders.push(new SchemaHeaderField('unset'));
         }
@@ -98,8 +114,6 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         if (this.columnHeaders === undefined) {
             this.dataDoc.columnHeaders = new List<SchemaHeaderField>([new SchemaHeaderField('New Column')]);
             // add all of the docs that have not been added to a column to this new column
-        } else {
-            this.resizeColumns(this.columnHeaders.length);
         }
     }
 
@@ -573,6 +587,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     };
 
     // called when adding a new columnHeader
+    @undoBatch
     @action
     addGroup = (value: string) => {
         if (value && this.columnHeaders) {
@@ -618,7 +633,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         //     sections = this.layoutDoc._columnsSort ? entries.sort(this.sortFunc) : entries;
         // }
         const entries = Array.from(this.Sections.entries());
-        const sections = entries.sort(this.sortFunc);
+        const sections = entries; //.sort(this.sortFunc);
         const eles: JSX.Element[] = [];
         for (let i = 0; i < sections.length; i++) {
             const col = this.sectionNoteTaking(sections[i][0], sections[i][1]);
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 9b7518c60..62d954b9c 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -47,6 +47,7 @@ interface CSVFieldColumnProps {
     screenToLocalTransform: () => Transform;
     observeHeight: (myref: any) => void;
     unobserveHeight: (myref: any) => void;
+    //setDraggedCol:(clonedDiv:any, header:SchemaHeaderField, xycoors: )
     editableViewProps: () => any;
     resizeColumns: (n: number) => void;
     columnStartXCoords: number[];
-- 
cgit v1.2.3-70-g09d2


From 51851e8f51f1700757119a09121db20c581a8325 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 5 Aug 2022 14:55:42 -0400
Subject: fix for deleting columns to properly trigger reactions and avoid
 index of out bounds

---
 src/client/views/collections/CollectionNoteTakingView.tsx  | 14 +++++---------
 .../views/collections/CollectionNoteTakingViewColumn.tsx   | 12 +++++++-----
 2 files changed, 12 insertions(+), 14 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 95aafce94..ec849d89d 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -2,7 +2,7 @@ import React = require('react');
 import { CursorProperty } from 'csstype';
 import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
-import { DataSym, Doc, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
+import { DataSym, Doc, Field, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
 import { Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
 import { listSpec } from '../../../fields/Schema';
@@ -327,15 +327,11 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     // how to get the width of a document. Currently returns the width of the column (minus margins)
     // if a note doc. Otherwise, returns the normal width (for graphs, images, etc...)
     getDocWidth(d: Doc) {
-        const heading = StrCast(d[this.notetakingCategoryField], 'unset');
+        const heading = !d[this.notetakingCategoryField] ? 'unset' : Field.toString(d[this.notetakingCategoryField] as Field);
         const existingHeader = this.columnHeaders.find(sh => sh.heading === heading);
-        const colStartXCoords = this.columnStartXCoords;
-        if (!existingHeader) {
-            return 1000;
-        }
-        const index = this.columnHeaders.indexOf(existingHeader);
-        const endColValue = index == this.columnHeaders.length - 1 ? this.PanelWidth : this.columnStartXCoords[index + 1];
-        const maxWidth = endColValue - colStartXCoords[index] - 3 * this.xMargin;
+        const index = existingHeader ? this.columnHeaders.indexOf(existingHeader) : 0;
+        const endColValue = index === this.columnHeaders.length - 1 || index > this.columnStartXCoords.length - 1 ? this.PanelWidth : this.columnStartXCoords[index + 1];
+        const maxWidth = index > this.columnStartXCoords.length - 1 ? this.PanelWidth : endColValue - this.columnStartXCoords[index] - 3 * this.xMargin;
         if (d.type === DocumentType.RTF) {
             return maxWidth;
         }
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 62d954b9c..624beca96 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -21,6 +21,8 @@ import { ContextMenuProps } from '../ContextMenuItem';
 import { EditableView } from '../EditableView';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
 import './CollectionNoteTakingView.scss';
+import { listSpec } from '../../../fields/Schema';
+import { Cast } from '../../../fields/Types';
 const higflyout = require('@hig/flyout');
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -67,7 +69,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
             return this.props.maxColWidth;
         }
         const i = this.props.columnHeaders.indexOf(this.props.headingObject);
-        if (i < 0) {
+        if (i < 0 || i > this.props.columnStartXCoords.length - 1) {
             return this.props.maxColWidth;
         }
         const endColValue = i == this.props.numGroupColumns - 1 ? this.props.PanelWidth : this.props.columnStartXCoords[i + 1];
@@ -147,11 +149,11 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
     @undoBatch
     @action
     deleteColumn = () => {
-        if (this.props.columnHeaders && this.props.headingObject) {
-            const index = this.props.columnHeaders.indexOf(this.props.headingObject);
+        const columnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null);
+        if (columnHeaders && this.props.headingObject) {
+            const index = columnHeaders.indexOf(this.props.headingObject);
             this.props.docList.forEach(d => (d[this.props.pivotField] = 'unset'));
-            this.props.columnHeaders.splice(index, 1);
-            this.props.resizeColumns(this.props.columnHeaders.length);
+            columnHeaders.splice(index, 1);
         }
     };
 
-- 
cgit v1.2.3-70-g09d2


From 92ccfc514a15b03e5a1c0cb7ccbe9c1fe5ce82ad Mon Sep 17 00:00:00 2001
From: ljungster <parkerljung@gmail.com>
Date: Thu, 11 Aug 2022 07:37:03 -0500
Subject: cc

---
 package-lock.json                                  | 39 ++++++++++++++++++++++
 package.json                                       |  7 ++--
 .../collections/CollectionNoteTakingViewColumn.tsx | 19 +++++++----
 3 files changed, 55 insertions(+), 10 deletions(-)

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

diff --git a/package-lock.json b/package-lock.json
index 3b9cda8bb..6149d9314 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5059,6 +5059,16 @@
             "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
             "dev": true
         },
+        "d": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
+            "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
+            "dev": true,
+            "requires": {
+                "es5-ext": "^0.10.50",
+                "type": "^1.0.1"
+            }
+        },
         "d3-array": {
             "version": "2.12.1",
             "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz",
@@ -6208,6 +6218,28 @@
                 "is-symbol": "^1.0.2"
             }
         },
+        "es5-ext": {
+            "version": "0.10.62",
+            "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
+            "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
+            "dev": true,
+            "requires": {
+                "es6-iterator": "^2.0.3",
+                "es6-symbol": "^3.1.3",
+                "next-tick": "^1.1.0"
+            }
+        },
+        "es6-iterator": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+            "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
+            "dev": true,
+            "requires": {
+                "d": "1",
+                "es5-ext": "^0.10.35",
+                "es6-symbol": "^3.1.1"
+            }
+        },
         "es6-promise": {
             "version": "3.2.1",
             "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz",
@@ -6219,6 +6251,7 @@
             "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
             "dev": true,
             "requires": {
+                "d": "^1.0.1",
                 "ext": "^1.1.2"
             }
         },
@@ -20715,6 +20748,12 @@
             "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
             "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
         },
+        "type": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
+            "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
+            "dev": true
+        },
         "type-check": {
             "version": "0.3.2",
             "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
diff --git a/package.json b/package.json
index 2e3ef0a07..177d3a5e6 100644
--- a/package.json
+++ b/package.json
@@ -66,17 +66,17 @@
         "@types/prosemirror-view": "^1.23.1",
         "@types/rc-switch": "^1.9.2",
         "@types/react": "^18.0.15",
-        "@types/react-icons": "^3.0.0",
-        "@types/react-reconciler": "^0.26.4",
-        "@types/react-transition-group": "^4.4.5",
         "@types/react-autosuggest": "^9.3.14",
         "@types/react-color": "^2.17.6",
         "@types/react-datepicker": "^3.1.8",
         "@types/react-dom": "^18.0.6",
         "@types/react-grid-layout": "^1.3.2",
+        "@types/react-icons": "^3.0.0",
         "@types/react-measure": "^2.0.8",
+        "@types/react-reconciler": "^0.26.4",
         "@types/react-select": "^3.1.2",
         "@types/react-table": "^6.8.9",
+        "@types/react-transition-group": "^4.4.5",
         "@types/request": "^2.48.8",
         "@types/request-promise": "^4.1.48",
         "@types/rimraf": "^2.0.5",
@@ -84,6 +84,7 @@
         "@types/shelljs": "^0.8.11",
         "@types/socket.io": "^2.1.13",
         "@types/socket.io-client": "^1.4.36",
+        "@types/socket.io-parser": "^3.0.0",
         "@types/typescript": "^2.0.0",
         "@types/uuid": "^3.4.10",
         "@types/valid-url": "^1.0.3",
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 4286da2e2..f58d8e937 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -51,8 +51,8 @@ interface CSVFieldColumnProps {
     unobserveHeight: (myref: any) => void;
     //setDraggedCol:(clonedDiv:any, header:SchemaHeaderField, xycoors: )
     editableViewProps: () => any;
-    resizeColumns: (n: number) => void;
-    columnStartXCoords: number[];
+    // resizeColumns: (n: number) => void;
+    // columnStartXCoords: number[];
     PanelWidth: number;
     maxColWidth: number;
     // docsByColumnHeader: Map<string, Doc[]>
@@ -69,12 +69,16 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
             return this.props.maxColWidth;
         }
         const i = this.props.columnHeaders.indexOf(this.props.headingObject);
-        if (i < 0 || i > this.props.columnStartXCoords.length - 1) {
-            return this.props.maxColWidth;
+        if (i >= 0 && this.props.columnHeaders[i].width > 0) {
+            return this.props.columnHeaders[i].width;
         }
-        const endColValue = i == this.props.numGroupColumns - 1 ? this.props.PanelWidth : this.props.columnStartXCoords[i + 1];
-        // TODO make the math work here. 35 is half of 70, which is the current width of the divider
-        return endColValue - this.props.columnStartXCoords[i] - 30;
+        return this.props.maxColWidth;
+        // if (i < 0 || i > this.props.columnStartXCoords.length - 1) {
+        //     return this.props.maxColWidth;
+        // }
+        // const endColValue = i == this.props.numGroupColumns - 1 ? this.props.PanelWidth : this.props.columnStartXCoords[i + 1];
+        // // TODO make the math work here. 35 is half of 70, which is the current width of the divider
+        // return endColValue - this.props.columnStartXCoords[i] - 30;
     }
 
     private dropDisposer?: DragManager.DragDropDisposer;
@@ -156,6 +160,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
             this.props.docList.forEach(d => (d[this.props.pivotField] = 'unset'));
             columnHeaders.splice(index, 1);
         }
+        // probably need to add something here for sizing purposes
     };
 
     menuCallback = (x: number, y: number) => {
-- 
cgit v1.2.3-70-g09d2


From 6f7a94b0fa65729f03b49e8aecf9eb3c8a2461ff Mon Sep 17 00:00:00 2001
From: ljungster <parkerljung@gmail.com>
Date: Fri, 12 Aug 2022 14:43:41 -0700
Subject: sizing works but undo redo no longer does

---
 .../views/collections/CollectionNoteTakingView.tsx | 40 ++++++++++++++--------
 .../collections/CollectionNoteTakingViewColumn.tsx | 23 ++++++++-----
 2 files changed, 40 insertions(+), 23 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index b3e154dac..0aa1b6839 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -72,7 +72,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         //     return 3 2 1 4 56
         // }
         if (needsUnsetCategory) {
-            columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, this.maxColWdith));
+            columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1));
         }
         return columnHeaders;
     }
@@ -103,16 +103,20 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     @computed get PanelWidth() {
         return this.props.PanelWidth();
     }
-    @computed get maxColWdith() {
+    @computed get maxColWidth() {
         return this.props.PanelWidth() - 2 * this.xMargin;
     }
+    @computed get availableWidth() {
+        const numDividers = this.columnHeaders.length - 1;
+        return this.maxColWidth - numDividers * this.dividerWidth;
+    }
 
     // If the user has not yet created any docs (in another view), this will create a single column. Otherwise,
     // it will adjust according to the
     constructor(props: any) {
         super(props);
         if (this.columnHeaders === undefined) {
-            this.dataDoc.columnHeaders = new List<SchemaHeaderField>([new SchemaHeaderField('New Column', undefined, undefined, this.maxColWdith)]);
+            this.dataDoc.columnHeaders = new List<SchemaHeaderField>([new SchemaHeaderField('New Column', undefined, undefined, 1)]);
             // add all of the docs that have not been added to a column to this new column
         }
     }
@@ -186,7 +190,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         // this._disposers.headers = reaction(
         //     () => this.columnHeaders.slice(),
         //     // TODO: is this correct?
-        //     headers => this.resizeColumns(headers.length, true),
+        //     headers => this.resizeColumns(headers.length, false),
         //     { fireImmediately: true }
         // );
     }
@@ -334,7 +338,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         const heading = !d[this.notetakingCategoryField] ? 'unset' : Field.toString(d[this.notetakingCategoryField] as Field);
         const existingHeader = this.columnHeaders.find(sh => sh.heading === heading);
         const existingWidth = existingHeader?.width ? existingHeader.width : 0;
-        const maxWidth = existingWidth > 0 ? existingWidth : this.maxColWdith - 2 * this.xMargin;
+        const maxWidth = existingWidth > 0 ? existingWidth * this.availableWidth - 2 * this.xMargin : this.maxColWidth - 2 * this.xMargin;
         // const index = existingHeader ? this.columnHeaders.indexOf(existingHeader) : 0;
         // const endColValue = index === this.columnHeaders.length - 1 || index > this.columnStartXCoords.length - 1 ? this.PanelWidth : this.columnStartXCoords[index + 1];
         // const maxWidth = index > this.columnStartXCoords.length - 1 ? this.PanelWidth : endColValue - this.columnStartXCoords[index] - 3 * this.xMargin;
@@ -367,10 +371,14 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     // called when a column is either added or deleted. This function creates n evenly spaced columns
     @action
     resizeColumns = (n: number, isAdd: boolean) => {
-        let scaleFactor = isAdd ? Math.floor((n - 1)) / n : Math.floor((n + 1) / n);
-        if (isAdd && n == 1) scaleFactor = 1;
+        if (n == 1) {
+          this.columnHeaders[0].setWidth(1);
+          return;
+        }
+        let scaleFactor = isAdd ? (n - 1) / n : (n + 1) / n;
+        // if (isAdd && n == 1) scaleFactor = 1;
         this.columnHeaders.forEach(h => {
-          h.width < 0 ? h.setWidth((this.maxColWdith - this.dividerWidth) / n) : h.setWidth(h.width * scaleFactor);
+            h.width < 0 ? h.setWidth(1 / n) : h.setWidth(h.width * scaleFactor);
         });
         // if we're adding, need to
 
@@ -424,7 +432,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         let colStartXCoord = 0;
         for (let i = 0; i < numColumns; i++) {
             coords.push(colStartXCoord);
-            colStartXCoord += this.columnHeaders[i].width + this.dividerWidth;
+            colStartXCoord += this.columnHeaders[i].width * this.availableWidth + this.dividerWidth;
         }
 
         coords.push(this.PanelWidth);
@@ -600,13 +608,15 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
                 columnHeaders={this.columnHeaders}
                 Document={this.props.Document}
                 DataDoc={this.props.DataDoc}
-                // resizeColumns={this.resizeColumns}
+                resizeColumns={this.resizeColumns}
                 renderChildren={this.children}
                 numGroupColumns={this.numGroupColumns}
                 gridGap={this.gridGap}
                 pivotField={this.notetakingCategoryField}
                 // columnStartXCoords={this.columnStartXCoords}
-                maxColWidth={this.maxColWdith}
+                dividerWidth={this.dividerWidth}
+                maxColWidth={this.maxColWidth}
+                availableWidth={this.availableWidth}
                 PanelWidth={this.PanelWidth}
                 key={heading?.heading ?? ''}
                 headings={this.headings}
@@ -628,9 +638,9 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     @undoBatch
     addGroup = (value: string) => {
         const columnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null);
-        const colWidth = (this.PanelWidth - this.numGroupColumns * this.dividerWidth) / (this.numGroupColumns + 1);
+        // const colWidth = (this.PanelWidth - this.numGroupColumns * this.dividerWidth) / (this.numGroupColumns + 1);
         this.resizeColumns(this.numGroupColumns + 1, true);
-        return value && columnHeaders?.push(new SchemaHeaderField(value, undefined, undefined, colWidth)) ? true : false;
+        return value && columnHeaders?.push(new SchemaHeaderField(value, undefined, undefined, 1 / (this.numGroupColumns + 1))) ? true : false;
     };
 
     sortFunc = (a: [SchemaHeaderField, Doc[]], b: [SchemaHeaderField, Doc[]]): 1 | -1 => {
@@ -656,8 +666,8 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     setColumnStartXCoords = (movementX: number, colIndex: number) => {
         const leftHeader = this.columnHeaders[colIndex];
         const rightHeader = this.columnHeaders[colIndex + 1];
-        leftHeader.setWidth(leftHeader.width + movementX);
-        rightHeader.setWidth(rightHeader.width - movementX);
+        leftHeader.setWidth(leftHeader.width + movementX / this.availableWidth);
+        rightHeader.setWidth(rightHeader.width - movementX / this.availableWidth);
         // const coords = [...this.columnStartXCoords];
         // coords[colIndex] += movementX;
         // this.columnStartXCoords = coords;
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index f58d8e937..8ad684cec 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -51,10 +51,12 @@ interface CSVFieldColumnProps {
     unobserveHeight: (myref: any) => void;
     //setDraggedCol:(clonedDiv:any, header:SchemaHeaderField, xycoors: )
     editableViewProps: () => any;
-    // resizeColumns: (n: number) => void;
+    resizeColumns: (n: number, isAdd: boolean) => void;
     // columnStartXCoords: number[];
     PanelWidth: number;
     maxColWidth: number;
+    dividerWidth: number;
+    availableWidth: number;
     // docsByColumnHeader: Map<string, Doc[]>
     // setDocsForColHeader: (key: string, docs: Doc[]) => void
 }
@@ -63,16 +65,22 @@ interface CSVFieldColumnProps {
 export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColumnProps> {
     @observable private _background = 'inherit';
 
+    // the "width" property of headers is relative (a percentage of available space)
     @computed get columnWidth() {
         // base cases
-        if (!this.props.columnHeaders || !this.props.headingObject || this.props.columnHeaders.length == 1) {
+        if (!this.props.columnHeaders || !this.props.headingObject) {
             return this.props.maxColWidth;
         }
-        const i = this.props.columnHeaders.indexOf(this.props.headingObject);
-        if (i >= 0 && this.props.columnHeaders[i].width > 0) {
-            return this.props.columnHeaders[i].width;
+        if (this.props.columnHeaders.length == 1) {
+            // this.props.columnHeaders[0].setWidth(1);
+            return this.props.maxColWidth;
         }
-        return this.props.maxColWidth;
+        const i = this.props.columnHeaders.indexOf(this.props.headingObject);
+        return this.props.columnHeaders[i].width * this.props.availableWidth;
+        // if (i >= 0 && this.props.columnHeaders[i].width > 0) {
+        //     return this.props.columnHeaders[i].width;
+        // }
+        // return this.props.maxColWidth;
         // if (i < 0 || i > this.props.columnStartXCoords.length - 1) {
         //     return this.props.maxColWidth;
         // }
@@ -150,7 +158,6 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
         return this.props.addDocument?.(newDoc) || false;
     };
 
-    @undoBatch
     @action
     @undoBatch
     deleteColumn = () => {
@@ -158,9 +165,9 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
         if (columnHeaders && this.props.headingObject) {
             const index = columnHeaders.indexOf(this.props.headingObject);
             this.props.docList.forEach(d => (d[this.props.pivotField] = 'unset'));
+            this.props.resizeColumns(columnHeaders.length - 1, false)
             columnHeaders.splice(index, 1);
         }
-        // probably need to add something here for sizing purposes
     };
 
     menuCallback = (x: number, y: number) => {
-- 
cgit v1.2.3-70-g09d2


From 5655589d46c01af74c959c2d365d3eeb15feb407 Mon Sep 17 00:00:00 2001
From: ljungster <parkerljung@gmail.com>
Date: Fri, 19 Aug 2022 06:48:46 -0500
Subject: persistent resizing undo/redo issues

---
 .../views/collections/CollectionNoteTakingView.tsx | 30 ++++++++++++++--------
 .../collections/CollectionNoteTakingViewColumn.tsx |  6 +++--
 2 files changed, 23 insertions(+), 13 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 0aa1b6839..447e1f0c8 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -368,18 +368,27 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         return Math.min(childHeight, maxHeight, panelHeight);
     }
 
-    // called when a column is either added or deleted. This function creates n evenly spaced columns
+    // called when a column is either added or deleted.
+    // TODO: this needs help still
     @action
-    resizeColumns = (n: number, isAdd: boolean) => {
+    resizeColumns = (isAdd: boolean, colWidth: number, colIndex: number) => {
+        const n = this.columnHeaders.length;
         if (n == 1) {
-          this.columnHeaders[0].setWidth(1);
-          return;
+            this.columnHeaders[0].setWidth(1);
+            return true;
         }
-        let scaleFactor = isAdd ? (n - 1) / n : (n + 1) / n;
-        // if (isAdd && n == 1) scaleFactor = 1;
-        this.columnHeaders.forEach(h => {
-            h.width < 0 ? h.setWidth(1 / n) : h.setWidth(h.width * scaleFactor);
+        const scaleFactor = isAdd ? 1 - colWidth : 1 / (1 - colWidth);
+        this.columnHeaders.forEach((h, i) => {
+            if (!(isAdd && i == colIndex)) {
+                h.width < 0 ? h.setWidth(1 / n) : h.setWidth(h.width * scaleFactor);
+            }
         });
+        return true;
+        // let scaleFactor = isAdd ? (n - 1) / n : (n + 1) / n;
+        // // if (isAdd && n == 1) scaleFactor = 1;
+        // this.columnHeaders.forEach(h => {
+        //     h.width < 0 ? h.setWidth(1 / n) : h.setWidth(h.width * scaleFactor);
+        // });
         // if we're adding, need to
 
         // const newColXCoords: number[] = [];
@@ -638,9 +647,8 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     @undoBatch
     addGroup = (value: string) => {
         const columnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null);
-        // const colWidth = (this.PanelWidth - this.numGroupColumns * this.dividerWidth) / (this.numGroupColumns + 1);
-        this.resizeColumns(this.numGroupColumns + 1, true);
-        return value && columnHeaders?.push(new SchemaHeaderField(value, undefined, undefined, 1 / (this.numGroupColumns + 1))) ? true : false;
+        const newColWidth = 1 / (this.numGroupColumns + 1);
+        return value && columnHeaders?.push(new SchemaHeaderField(value, undefined, undefined, newColWidth)) && this.resizeColumns(true, newColWidth, this.columnHeaders.length - 1) ? true : false;
     };
 
     sortFunc = (a: [SchemaHeaderField, Doc[]], b: [SchemaHeaderField, Doc[]]): 1 | -1 => {
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 8ad684cec..11a0e69ac 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -51,7 +51,7 @@ interface CSVFieldColumnProps {
     unobserveHeight: (myref: any) => void;
     //setDraggedCol:(clonedDiv:any, header:SchemaHeaderField, xycoors: )
     editableViewProps: () => any;
-    resizeColumns: (n: number, isAdd: boolean) => void;
+    resizeColumns: (isAdd: boolean, colWidth: number, colIndex: number) => boolean;
     // columnStartXCoords: number[];
     PanelWidth: number;
     maxColWidth: number;
@@ -165,8 +165,10 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
         if (columnHeaders && this.props.headingObject) {
             const index = columnHeaders.indexOf(this.props.headingObject);
             this.props.docList.forEach(d => (d[this.props.pivotField] = 'unset'));
-            this.props.resizeColumns(columnHeaders.length - 1, false)
+            // should never be 0, currently placeholder
+            const colWidth = this.props.columnHeaders ? this.props.columnHeaders[index].width : 0;
             columnHeaders.splice(index, 1);
+            this.props.resizeColumns(false, colWidth, index);
         }
     };
 
-- 
cgit v1.2.3-70-g09d2


From b7c2e1081e4efe7167a86fb1d9f641bea8b93bba Mon Sep 17 00:00:00 2001
From: ljungster <parkerljung@gmail.com>
Date: Mon, 22 Aug 2022 05:51:13 -0500
Subject: commented all NoteTakingView files

---
 .../views/collections/CollectionNoteTakingView.tsx | 17 ++++++----
 .../collections/CollectionNoteTakingViewColumn.tsx | 38 ++++++----------------
 .../CollectionNoteTakingViewDivider.tsx            |  6 +++-
 3 files changed, 25 insertions(+), 36 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index a2f05c031..9e40356d6 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -1,6 +1,6 @@
 import React = require('react');
 import { CursorProperty } from 'csstype';
-import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import { DataSym, Doc, Field, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
 import { Id } from '../../../fields/FieldSymbols';
@@ -55,7 +55,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     @computed get chromeHidden() {
         return this.props.chromeHidden || BoolCast(this.layoutDoc.chromeHidden);
     }
-    // columnHeaders() returns the list of SchemaHeaderFields currently being used by the layout doc to render the columns
+    // 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'));
@@ -64,19 +64,17 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         }
         return columnHeaders;
     }
-    // 
+    // notetakingCategoryField returns the key to accessing a document's column value
     @computed get notetakingCategoryField() {
         return 'NotetakingCategory';
     }
-    @computed get filteredChildren() {
-        return this.childLayoutPairs.filter(pair => pair.layout instanceof Doc && !pair.layout.hidden).map(pair => pair.layout);
-    }
     @computed get headerMargin() {
         return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin);
     }
     @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;
     }
@@ -86,15 +84,20 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
     @computed get gridGap() {
         return NumCast(this.layoutDoc._gridGap, 10);
     }
+    // numGroupColumns returns the number of columns
     @computed get numGroupColumns() {
         return this.columnHeaders.length;
     }
+    // PanelWidth returns the size of the total available space the view occupies
     @computed get PanelWidth() {
         return this.props.PanelWidth();
     }
+    // maxColWidth returns the maximum column width, which is slightly less than the total available space.
     @computed get maxColWidth() {
         return this.props.PanelWidth() - 2 * this.xMargin;
     }
+    // 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;
         return this.maxColWidth - numDividers * this.dividerWidth;
@@ -109,7 +112,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         }
     }
 
-    // passed as a prop to the NoteTakingField, which uses this function
+    // 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[]) => {
         TraceMobx();
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 11a0e69ac..a866373a9 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -5,11 +5,12 @@ import { observer } from 'mobx-react';
 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';
-import { ScriptField } from '../../../fields/ScriptField';
+import { Cast } from '../../../fields/Types';
 import { ImageField } from '../../../fields/URLField';
 import { TraceMobx } from '../../../fields/util';
-import { emptyFunction, returnEmptyString, setupMoveUpEvents } from '../../../Utils';
+import { returnEmptyString } from '../../../Utils';
 import { Docs, DocUtils } from '../../documents/Documents';
 import { DocumentType } from '../../documents/DocumentTypes';
 import { DragManager } from '../../util/DragManager';
@@ -21,13 +22,10 @@ import { ContextMenuProps } from '../ContextMenuItem';
 import { EditableView } from '../EditableView';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
 import './CollectionNoteTakingView.scss';
-import { listSpec } from '../../../fields/Schema';
-import { Cast } from '../../../fields/Types';
 const higflyout = require('@hig/flyout');
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
 
-// So this is how we are storing a column
 interface CSVFieldColumnProps {
     Document: Doc;
     DataDoc: Opt<Doc>;
@@ -38,7 +36,6 @@ interface CSVFieldColumnProps {
     columnHeaders: SchemaHeaderField[] | undefined;
     headingObject: SchemaHeaderField | undefined;
     yMargin: number;
-    // columnWidth: number;
     numGroupColumns: number;
     gridGap: number;
     type: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | undefined;
@@ -49,44 +46,32 @@ interface CSVFieldColumnProps {
     screenToLocalTransform: () => Transform;
     observeHeight: (myref: any) => void;
     unobserveHeight: (myref: any) => void;
-    //setDraggedCol:(clonedDiv:any, header:SchemaHeaderField, xycoors: )
     editableViewProps: () => any;
     resizeColumns: (isAdd: boolean, colWidth: number, colIndex: number) => boolean;
-    // columnStartXCoords: number[];
     PanelWidth: number;
     maxColWidth: number;
     dividerWidth: number;
     availableWidth: number;
-    // docsByColumnHeader: Map<string, Doc[]>
-    // setDocsForColHeader: (key: string, docs: Doc[]) => void
 }
 
+/**
+ * CollectionNoteTakingViewColumn represents an individual column rendered in CollectionNoteTakingView. The
+ * majority of functions here are for rendering styles.
+ */
 @observer
 export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColumnProps> {
     @observable private _background = 'inherit';
 
-    // the "width" property of headers is relative (a percentage of available space)
+    // columnWidth returns the width of a column in absolute pixels
     @computed get columnWidth() {
-        // base cases
         if (!this.props.columnHeaders || !this.props.headingObject) {
             return this.props.maxColWidth;
         }
         if (this.props.columnHeaders.length == 1) {
-            // this.props.columnHeaders[0].setWidth(1);
             return this.props.maxColWidth;
         }
         const i = this.props.columnHeaders.indexOf(this.props.headingObject);
         return this.props.columnHeaders[i].width * this.props.availableWidth;
-        // if (i >= 0 && this.props.columnHeaders[i].width > 0) {
-        //     return this.props.columnHeaders[i].width;
-        // }
-        // return this.props.maxColWidth;
-        // if (i < 0 || i > this.props.columnStartXCoords.length - 1) {
-        //     return this.props.maxColWidth;
-        // }
-        // const endColValue = i == this.props.numGroupColumns - 1 ? this.props.PanelWidth : this.props.columnStartXCoords[i + 1];
-        // // TODO make the math work here. 35 is half of 70, which is the current width of the divider
-        // return endColValue - this.props.columnStartXCoords[i] - 30;
     }
 
     private dropDisposer?: DragManager.DragDropDisposer;
@@ -96,8 +81,6 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
     @observable _color = this.props.headingObject ? this.props.headingObject.color : '#f1efeb';
     _ele: HTMLElement | null = null;
 
-    // This is likely similar to what we will be doing. Why do we need to make these refs?
-    // is that the only way to have drop targets?
     createColumnDropRef = (ele: HTMLDivElement | null) => {
         this.dropDisposer?.();
         if (ele) {
@@ -146,6 +129,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
     @action pointerLeave = () => (this._background = 'inherit');
     textCallback = (char: string) => this.addNewTextDoc('-typed text-', false, true);
 
+    // addNewTextDoc is called when a user starts typing in a column to create a new node
     @action
     addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => {
         if (!value && !forceEmptyNote) return false;
@@ -158,6 +142,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
         return this.props.addDocument?.(newDoc) || false;
     };
 
+    // deleteColumn is called when a user deletes a column using the 'trash' icon in the button area. 
     @action
     @undoBatch
     deleteColumn = () => {
@@ -270,7 +255,6 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
                 </div>
             </div>
         ) : null;
-        // const templatecols = `${this.props.columnWidth / this.props.numGroupColumns}px `;
         const templatecols = `${this.columnWidth}px `;
         const type = this.props.Document.type;
         return (
@@ -297,7 +281,6 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
                         {!this.props.chromeHidden && type !== DocumentType.PRES ? (
                             <div
                                 className="collectionNoteTakingView-DocumentButtons"
-                                // style={{ width: this.props.columnWidth / this.props.numGroupColumns, marginBottom: 10 }}>
                                 style={{ width: this.columnWidth - 20, marginBottom: 10 }}>
                                 <div key={`${heading}-add-document`} className="collectionNoteTakingView-addDocumentButton">
                                     <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} textCallback={this.textCallback} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} />
@@ -326,7 +309,6 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
                 className={'collectionNoteTakingViewFieldColumn' + (SnappingManager.GetIsDragging() ? 'Dragging' : '')}
                 key={heading}
                 style={{
-                    //TODO: change this so that it's based on the column width
                     width: this.columnWidth,
                     background: this._background,
                 }}
diff --git a/src/client/views/collections/CollectionNoteTakingViewDivider.tsx b/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
index 2633bffeb..7defeb031 100644
--- a/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
@@ -1,7 +1,6 @@
 import { action, observable } from 'mobx';
 import * as React from 'react';
 import { emptyFunction, setupMoveUpEvents } from '../../../Utils';
-import { Transform } from '../../util/Transform';
 import { UndoManager } from '../../util/UndoManager';
 
 interface DividerProps {
@@ -10,6 +9,11 @@ interface DividerProps {
     setColumnStartXCoords: (movementX: number, colIndex: number) => void;
 }
 
+/**
+ * CollectionNoteTakingViewDivider is a divider between CollectionNoteTakingViewColumns,
+ * which only appear when there is more than 1 column in CollectionNoteTakingView. Dividers
+ * are two simple vertical lines that allow the user to alter the widths of CollectionNoteTakingViewColumns.
+ */
 export class CollectionNoteTakingViewDivider extends React.Component<DividerProps> {
     @observable private isHoverActive = false;
     @observable private isResizingActive = false;
-- 
cgit v1.2.3-70-g09d2


From 3cf60a6118a5994e43c8ac9d00092992d6c83700 Mon Sep 17 00:00:00 2001
From: ljungster <parkerljung@gmail.com>
Date: Mon, 22 Aug 2022 11:03:31 -0400
Subject: can't add column if name in use

---
 src/client/views/collections/CollectionNoteTakingView.tsx  |  9 +++++++--
 .../views/collections/CollectionNoteTakingViewColumn.tsx   | 14 ++++++++------
 .../views/collections/CollectionNoteTakingViewDivider.tsx  |  2 +-
 3 files changed, 16 insertions(+), 9 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 9e40356d6..16fefc55a 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -587,10 +587,15 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
 
     // 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
     @action
     @undoBatch
     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;
+          }
+        }
         const columnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null);
         const newColWidth = 1 / (this.numGroupColumns + 1);
         return value && columnHeaders?.push(new SchemaHeaderField(value, undefined, undefined, newColWidth)) && this.resizeColumns(true, newColWidth, this.columnHeaders.length - 1) ? true : false;
@@ -607,7 +612,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
         }
     };
 
-    // setColumnStartXCoords is used to update column sizes when using the drag handlers between columns
+    // setColumnStartXCoords is used to update column widths when using the drag handlers between columns
     @action
     setColumnStartXCoords = (movementXScreen: number, colIndex: number) => {
         const movementX = this.props.ScreenToLocalTransform().transformDirection(movementXScreen, 0)[0];
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index a866373a9..e619b084b 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -142,15 +142,19 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
         return this.props.addDocument?.(newDoc) || false;
     };
 
-    // deleteColumn is called when a user deletes a column using the 'trash' icon in the button area. 
+    // deleteColumn is called when a user deletes a column using the 'trash' icon in the button area.
+    // If the user deletes the first column, the documents get moved to the second column. Otherwise,
+    // all docs are added to the column directly to the left.
     @action
     @undoBatch
     deleteColumn = () => {
         const columnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null);
         if (columnHeaders && this.props.headingObject) {
             const index = columnHeaders.indexOf(this.props.headingObject);
-            this.props.docList.forEach(d => (d[this.props.pivotField] = 'unset'));
-            // should never be 0, currently placeholder
+            const newColIndex = index > 0 ? index - 1 : 1;
+            const newColHeader = this.props.columnHeaders ? this.props.columnHeaders[newColIndex] : undefined;
+            const newHeading = newColHeader ? newColHeader.heading : 'unset';
+            this.props.docList.forEach(d => (d[this.props.pivotField] = newHeading));
             const colWidth = this.props.columnHeaders ? this.props.columnHeaders[index].width : 0;
             columnHeaders.splice(index, 1);
             this.props.resizeColumns(false, colWidth, index);
@@ -279,9 +283,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
                         </div>
 
                         {!this.props.chromeHidden && type !== DocumentType.PRES ? (
-                            <div
-                                className="collectionNoteTakingView-DocumentButtons"
-                                style={{ width: this.columnWidth - 20, marginBottom: 10 }}>
+                            <div className="collectionNoteTakingView-DocumentButtons" style={{ width: this.columnWidth - 20, marginBottom: 10 }}>
                                 <div key={`${heading}-add-document`} className="collectionNoteTakingView-addDocumentButton">
                                     <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} textCallback={this.textCallback} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} />
                                 </div>
diff --git a/src/client/views/collections/CollectionNoteTakingViewDivider.tsx b/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
index 7defeb031..8d659f790 100644
--- a/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
@@ -10,7 +10,7 @@ interface DividerProps {
 }
 
 /**
- * CollectionNoteTakingViewDivider is a divider between CollectionNoteTakingViewColumns,
+ * CollectionNoteTakingViewDivider are dividers between CollectionNoteTakingViewColumns,
  * which only appear when there is more than 1 column in CollectionNoteTakingView. Dividers
  * are two simple vertical lines that allow the user to alter the widths of CollectionNoteTakingViewColumns.
  */
-- 
cgit v1.2.3-70-g09d2


From 7f4f2840cd64c1eb40851c2ee410fa1905288b73 Mon Sep 17 00:00:00 2001
From: ljungster <parkerljung@gmail.com>
Date: Mon, 22 Aug 2022 15:53:08 -0400
Subject: c

---
 src/client/views/collections/CollectionNoteTakingView.tsx       | 2 +-
 src/client/views/collections/CollectionNoteTakingViewColumn.tsx | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 16fefc55a..302c4eaea 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -587,8 +587,8 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti
 
     // 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.
-    @action
     @undoBatch
+    @action
     addGroup = (value: string) => {
         for (const header of this.columnHeaders) {
           if (header.heading == value) {
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index e619b084b..4610da4e3 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -145,8 +145,8 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
     // deleteColumn is called when a user deletes a column using the 'trash' icon in the button area.
     // If the user deletes the first column, the documents get moved to the second column. Otherwise,
     // all docs are added to the column directly to the left.
-    @action
     @undoBatch
+    @action
     deleteColumn = () => {
         const columnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null);
         if (columnHeaders && this.props.headingObject) {
-- 
cgit v1.2.3-70-g09d2


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.

---
 src/client/util/CurrentUserUtils.ts                |  11 ++-
 .../views/collections/CollectionNoteTakingView.tsx | 103 ++++++++-------------
 .../collections/CollectionNoteTakingViewColumn.tsx |  12 ++-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  18 ++--
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  10 +-
 src/client/views/nodes/DocumentView.scss           |   3 +
 src/fields/SchemaHeaderField.ts                    |   2 +-
 src/fields/ScriptField.ts                          |  10 +-
 8 files changed, 79 insertions(+), 90 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 99a8c895f..2321d18ee 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -597,14 +597,17 @@ export class CurrentUserUtils {
     /// initializes the required buttons in the expanding button menu at the bottom of the Dash window
     static setupDockedButtons(doc: Doc, field="myDockedBtns") {
         const dockedBtns = DocCast(doc[field]);
-        const dockBtn = (opts: DocumentOptions, scripts: {[key:string]:string}) =>
+        const dockBtn = (opts: DocumentOptions, scripts: {[key:string]:string}, funcs?: {[key:string]:string}) =>
             DocUtils.AssignScripts(DocUtils.AssignOpts(DocListCast(dockedBtns?.data)?.find(doc => doc.title === opts.title), opts) ?? 
-                            CurrentUserUtils.createToolButton(opts), scripts);
+                            CurrentUserUtils.createToolButton(opts), scripts, funcs);
         
         const btnDescs = [// setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet
             { scripts: { onClick: "undo()"}, opts: { title: "undo", icon: "undo-alt", toolTip: "Click to undo" }},
-            { scripts: { onClick: "redo()"}, opts: { title: "redo", icon: "redo-alt", toolTip: "Click to redo" }}
-        ];
+            { scripts: { onClick: "redo()"}, opts: { title: "redo", icon: "redo-alt", toolTip: "Click to redo" }},
+            // { scripts: { onClick: 'prevKeyFrame(_readOnly_)'}, opts: { title: "Back", icon: "chevron-left", toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton,   width: 20}},
+            // { scripts: { onClick:""}, opts:  { title: "Num", icon: "",  toolTip: "Frame Number",  btnType: ButtonType.TextButton,  width: 20}, funcs: { buttonText: 'selectedDocs()?.lastElement()?.currentFrame.toString()'}},
+            // { scripts: { onClick: 'nextKeyFrame(_readOnly_)'}, opts:{title: "Fwd",     icon: "chevron-right", toolTip: "Next Animation Frame", btnType: ButtonType.ClickButton,  width: 20,}  },
+             ];
         const btns = btnDescs.map(desc => dockBtn({_width: 30, _height: 30, dontUndo: true, _stayInCollection: true, ...desc.opts}, desc.scripts));
         const dockBtnsReqdOpts = {
             title: "docked buttons", _height: 40, flexGap: 0, linearViewFloating: true,
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() {
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 4610da4e3..c57677683 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -3,7 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import { Doc, DocListCast, Opt } from '../../../fields/Doc';
-import { Id } from '../../../fields/FieldSymbols';
+import { Copy, Id } from '../../../fields/FieldSymbols';
 import { RichTextField } from '../../../fields/RichTextField';
 import { listSpec } from '../../../fields/Schema';
 import { SchemaHeaderField } from '../../../fields/SchemaHeaderField';
@@ -22,6 +22,8 @@ import { ContextMenuProps } from '../ContextMenuItem';
 import { EditableView } from '../EditableView';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
 import './CollectionNoteTakingView.scss';
+import { List } from '../../../fields/List';
+import { Field } from '../../util/ProsemirrorCopy/prompt';
 const higflyout = require('@hig/flyout');
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -148,15 +150,17 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
     @undoBatch
     @action
     deleteColumn = () => {
-        const columnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null);
-        if (columnHeaders && this.props.headingObject) {
-            const index = columnHeaders.indexOf(this.props.headingObject);
+        const acolumnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null);
+        if (acolumnHeaders && this.props.headingObject) {
+            const index = acolumnHeaders.indexOf(this.props.headingObject);
+            const columnHeaders = new List<SchemaHeaderField>(acolumnHeaders.map(header => header[Copy]())); // needed for undo to work properly.  otherwise we end up changing field values in the undo stack since they are shared by reference
             const newColIndex = index > 0 ? index - 1 : 1;
             const newColHeader = this.props.columnHeaders ? this.props.columnHeaders[newColIndex] : undefined;
             const newHeading = newColHeader ? newColHeader.heading : 'unset';
             this.props.docList.forEach(d => (d[this.props.pivotField] = newHeading));
             const colWidth = this.props.columnHeaders ? this.props.columnHeaders[index].width : 0;
             columnHeaders.splice(index, 1);
+            Doc.GetProto(this.props.Document).columnHeaders = columnHeaders;
             this.props.resizeColumns(false, colWidth, index);
         }
     };
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 052cbd3bb..c44b33ed0 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -44,7 +44,6 @@ import { PresBox } from '../../nodes/trails/PresBox';
 import { VideoBox } from '../../nodes/VideoBox';
 import { CreateImage } from '../../nodes/WebBoxRenderer';
 import { StyleProp } from '../../StyleProvider';
-import { CollectionDockingView } from '../CollectionDockingView';
 import { CollectionSubView } from '../CollectionSubView';
 import { TreeViewType } from '../CollectionTreeView';
 import { TabDocView } from '../TabDocView';
@@ -233,11 +232,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             const newBoxes = newBox instanceof Doc ? [newBox] : newBox;
             for (const newBox of newBoxes) {
                 if (newBox.activeFrame !== undefined) {
-                    const vals = CollectionFreeFormDocumentView.animFields.map(field => newBox[field]);
-                    CollectionFreeFormDocumentView.animFields.forEach(field => delete newBox[`${field}-indexed`]);
-                    CollectionFreeFormDocumentView.animFields.forEach(field => delete newBox[field]);
+                    const vals = CollectionFreeFormDocumentView.animFields.map(field => newBox[field.key]);
+                    CollectionFreeFormDocumentView.animFields.forEach(field => delete newBox[`${field.key}-indexed`]);
+                    CollectionFreeFormDocumentView.animFields.forEach(field => delete newBox[field.key]);
                     delete newBox.activeFrame;
-                    CollectionFreeFormDocumentView.animFields.forEach((field, i) => field !== 'opacity' && (newBox[field] = vals[i]));
+                    CollectionFreeFormDocumentView.animFields.forEach((field, i) => field.key !== 'opacity' && (newBox[field.key] = vals[i]));
                 }
             }
             if (this.Document._currentFrame !== undefined && !this.props.isAnnotationOverlay) {
@@ -275,10 +274,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             const layoutDoc = Doc.Layout(d);
             if (this.Document._currentFrame !== undefined) {
                 CollectionFreeFormDocumentView.setupKeyframes([d], NumCast(this.Document._currentFrame), false);
-                const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000));
-                vals.x = x + NumCast(vals.x) - dropPos[0];
-                vals.y = y + NumCast(vals.y) - dropPos[1];
-                vals._scrollTop = this.Document.editScrollProgressivize ? vals._scrollTop : undefined;
+                const pvals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000)); // get filled in values (uses defaults when not value is specified) for position
+                const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000), false); // get non-default values for everything else
+                vals.x = x + NumCast(pvals.x) - dropPos[0];
+                vals.y = y + NumCast(pvals.y) - dropPos[1];
+                vals._scrollTop = this.Document.editScrollProgressivize ? pvals._scrollTop : undefined;
                 CollectionFreeFormDocumentView.setValues(NumCast(this.Document._currentFrame), d, vals);
             } else {
                 d.x = x + NumCast(d.x) - dropPos[0];
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 86566ac6a..efaecb8d2 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -36,7 +36,7 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
 
 @observer
 export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps>() {
-    public static animFields = ['_height', '_width', 'x', 'y', '_scrollTop', 'opacity']; // fields that are configured to be animatable using animation frames
+    public static animFields: { key: string; val?: number }[] = [{ key: '_height' }, { key: '_width' }, { key: 'x' }, { key: 'y' }, { key: '_scrollTop' }, { key: 'opacity', val: 1 }, { key: 'viewScale', val: 1 }, { key: 'panX' }, { key: 'panY' }]; // fields that are configured to be animatable using animation frames
     public static animStringFields = ['backgroundColor', 'color']; // fields that are configured to be animatable using animation frames
     public static animDataFields = ['data', 'text']; // fields that are configured to be animatable using animation frames
     @observable _animPos: number[] | undefined = undefined;
@@ -88,9 +88,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
         return this.props.styleProvider?.(doc, props, property);
     };
 
-    public static getValues(doc: Doc, time: number) {
+    public static getValues(doc: Doc, time: number, fillIn: boolean = true) {
         return CollectionFreeFormDocumentView.animFields.reduce((p, val) => {
-            p[val] = Cast(`${val}-indexed`, listSpec('number'), [NumCast(doc[val])]).reduce((p, v, i) => ((i <= Math.round(time) && v !== undefined) || p === undefined ? v : p), undefined as any as number);
+            p[val.key] = Cast(`${val}-indexed`, listSpec('number'), fillIn ? [NumCast(doc[val.key], val.val)] : []).reduce((p, v, i) => ((i <= Math.round(time) && v !== undefined) || p === undefined ? v : p), undefined as any as number);
             return p;
         }, {} as { [val: string]: Opt<number> });
     }
@@ -117,7 +117,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             action(doc => {
                 doc._viewTransition = doc.dataTransition = 'all 1s';
                 CollectionFreeFormDocumentView.animFields.forEach(val => {
-                    const findexed = Cast(doc[`${val}-indexed`], listSpec('number'), null);
+                    const findexed = Cast(doc[`${val.key}-indexed`], listSpec('number'), null);
                     findexed?.length <= timecode + 1 && findexed.push(undefined as any as number);
                 });
                 CollectionFreeFormDocumentView.animStringFields.forEach(val => {
@@ -174,7 +174,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                 // opacity is unlike other fields because it's value should not be undefined before it appears to enable it to fade-in
                 doc['opacity-indexed'] = new List<number>(numberRange(currTimecode + 1).map(t => (!doc.z && makeAppear && t < NumCast(doc.appearFrame) ? 0 : 1)));
             }
-            CollectionFreeFormDocumentView.animFields.forEach(val => (doc[val] = ComputedField.MakeInterpolatedNumber(val, 'activeFrame', doc, currTimecode)));
+            CollectionFreeFormDocumentView.animFields.forEach(val => (doc[val.key] = ComputedField.MakeInterpolatedNumber(val.key, 'activeFrame', doc, currTimecode, val.val)));
             CollectionFreeFormDocumentView.animStringFields.forEach(val => (doc[val] = ComputedField.MakeInterpolatedString(val, 'activeFrame', doc, currTimecode)));
             CollectionFreeFormDocumentView.animDataFields.forEach(val => (Doc.GetProto(doc)[val] = ComputedField.MakeInterpolatedDataField(val, 'activeFrame', Doc.GetProto(doc), currTimecode)));
             const targetDoc = doc.type === DocumentType.RTF ? Doc.GetProto(doc) : doc; // data fields, like rtf 'text' exist on the data doc, so
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index 9aaaf1e68..ab7116150 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -2,6 +2,7 @@
 
 .documentView-effectsWrapper {
     border-radius: inherit;
+    transition: inherit;
 }
 
 // documentViews have a docView-hack tag which is replaced by this tag when capturing bitmaps (when the dom is converted to an html string)
@@ -212,10 +213,12 @@
     display: flex;
     width: 100%;
     height: 100%;
+    transition: inherit;
 
     .contentFittingDocumentView-previewDoc {
         position: relative;
         display: inline;
+        transition: inherit;
     }
 
     .contentFittingDocumentView-input {
diff --git a/src/fields/SchemaHeaderField.ts b/src/fields/SchemaHeaderField.ts
index 1321bc327..0b51db70b 100644
--- a/src/fields/SchemaHeaderField.ts
+++ b/src/fields/SchemaHeaderField.ts
@@ -115,7 +115,7 @@ export class SchemaHeaderField extends ObjectField {
     }
 
     [ToScriptString]() {
-        return `header(${this.heading},${this.type}})`;
+        return `header(${this.heading},${this.type},${this.width}})`;
     }
     [ToString]() {
         return `SchemaHeaderField`;
diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts
index 48d5c5563..d38a019b3 100644
--- a/src/fields/ScriptField.ts
+++ b/src/fields/ScriptField.ts
@@ -189,13 +189,13 @@ export class ComputedField extends ScriptField {
         const compiled = ScriptField.CompileScript(script, params, true, capturedVariables);
         return compiled.compiled ? new ComputedField(compiled) : undefined;
     }
-    public static MakeInterpolatedNumber(fieldKey: string, interpolatorKey: string, doc: Doc, curTimecode: number) {
+    public static MakeInterpolatedNumber(fieldKey: string, interpolatorKey: string, doc: Doc, curTimecode: number, defaultVal: Opt<number>) {
         if (!doc[`${fieldKey}-indexed`]) {
             const flist = new List<number>(numberRange(curTimecode + 1).map(i => undefined) as any as number[]);
-            flist[curTimecode] = NumCast(doc[fieldKey]);
+            flist[curTimecode] = Cast(doc[fieldKey], 'number', null);
             doc[`${fieldKey}-indexed`] = flist;
         }
-        const getField = ScriptField.CompileScript(`getIndexVal(self['${fieldKey}-indexed'], self.${interpolatorKey})`, {}, true, {});
+        const getField = ScriptField.CompileScript(`getIndexVal(self['${fieldKey}-indexed'], self.${interpolatorKey}, ${defaultVal})`, {}, true, {});
         const setField = ScriptField.CompileScript(`setIndexVal(self['${fieldKey}-indexed'], self.${interpolatorKey}, value)`, { value: 'any' }, true, {});
         return getField.compiled ? new ComputedField(getField, setField?.compiled ? setField : undefined) : undefined;
     }
@@ -260,8 +260,8 @@ ScriptingGlobals.add(
 );
 
 ScriptingGlobals.add(
-    function getIndexVal(list: any[], index: number) {
-        return list?.reduce((p, x, i) => ((i <= index && x !== undefined) || p === undefined ? x : p), undefined as any);
+    function getIndexVal(list: any[], index: number, defaultVal: Opt<number> = undefined) {
+        return list?.reduce((p, x, i) => ((i <= index && x !== undefined) || p === undefined ? x : p), defaultVal);
     },
     'returns the value at a given index of a list',
     '(list: any[], index: number)'
-- 
cgit v1.2.3-70-g09d2


From ef2cd862c062556008a1897b408399dedaee8210 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 25 Aug 2022 17:04:53 -0400
Subject: fixed issues with reloading notetaking view and having columns be
 exactly the same.  fixed adding columns so that changes are actually
 propagated to the DB.  SchemaHeaderFields are bad news...

---
 .../collections/CollectionNoteTakingView.scss      | 32 +++++---
 .../views/collections/CollectionNoteTakingView.tsx | 42 +++++-----
 .../collections/CollectionNoteTakingViewColumn.tsx | 89 +++++++++-------------
 .../CollectionNoteTakingViewDivider.tsx            |  1 -
 4 files changed, 80 insertions(+), 84 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.scss b/src/client/views/collections/CollectionNoteTakingView.scss
index fe98f307e..5582fd391 100644
--- a/src/client/views/collections/CollectionNoteTakingView.scss
+++ b/src/client/views/collections/CollectionNoteTakingView.scss
@@ -1,7 +1,7 @@
 @import '../global/globalCssVariables';
 
 .collectionNoteTakingView-DocumentButtons {
-    display: flex;
+    display: none;
     justify-content: space-between;
     margin: auto;
 }
@@ -51,6 +51,17 @@
     display: flex;
 }
 
+.collectionNoteTakingViewFieldColumn {
+    height: 100%;
+    display: flex;
+    flex-direction: colum;
+}
+.collectionNoteTakingViewFieldColumn:hover {
+    .collectionNoteTakingView-DocumentButtons {
+        display: flex;
+    }
+}
+
 // TODO:glr Turn this into a seperate class
 .documentButtonMenu {
     position: relative;
@@ -82,7 +93,6 @@
     top: 0;
     overflow-y: auto;
     overflow-x: hidden;
-    flex-wrap: wrap;
     transition: top 0.5s;
 
     > div {
@@ -133,6 +143,16 @@
         margin-left: -5;
     }
 
+    .collectionNoteTakingView-sectionDelete {
+        display: none;
+        position: absolute;
+        right: 0;
+        width: max-content;
+        height: max-content;
+        top: 10;
+        padding: 2;
+    }
+
     // Documents in NoteTaking view
     .collectionNoteTakingView-columnDoc {
         display: flex;
@@ -347,14 +367,6 @@
                 }
             }
         }
-
-        .collectionNoteTakingView-sectionDelete {
-            position: absolute;
-            right: 25px;
-            top: 0;
-            height: 100%;
-            display: none;
-        }
     }
 
     .collectionNoteTakingView-sectionHeader:hover {
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 5a6d899ef..615141485 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -3,7 +3,7 @@ import { CursorProperty } from 'csstype';
 import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import { DataSym, Doc, Field, HeightSym, Opt, WidthSym } from '../../../fields/Doc';
-import { Id } from '../../../fields/FieldSymbols';
+import { Copy, Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
 import { listSpec } from '../../../fields/Schema';
 import { SchemaHeaderField } from '../../../fields/SchemaHeaderField';
@@ -42,7 +42,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
     _masonryGridRef: HTMLDivElement | null = null;
     _draggerRef = React.createRef<HTMLDivElement>();
     notetakingCategoryField = 'NotetakingCategory';
-    dividerWidth = 16;
+    public DividerWidth = 16;
     @observable docsDraggedRowCol: number[] = [];
     @observable _cursor: CursorProperty = 'grab';
     @observable _scroll = 0;
@@ -53,10 +53,11 @@ export class CollectionNoteTakingView extends CollectionSubView() {
     @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'));
-        if (needsUnsetCategory) {
+        if (needsUnsetCategory || columnHeaders === undefined || columnHeaders.length === 0) {
             setTimeout(() => {
+                const columnHeaders = Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null);
                 const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset'));
-                if (needsUnsetCategory) {
+                if (needsUnsetCategory || columnHeaders === undefined || columnHeaders.length === 0) {
                     if (columnHeaders) columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1));
                     else this.dataDoc.columnHeaders = new List<SchemaHeaderField>();
                 }
@@ -68,10 +69,10 @@ export class CollectionNoteTakingView extends CollectionSubView() {
         return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin);
     }
     @computed get xMargin() {
-        return NumCast(this.layoutDoc._xMargin, 2 * Math.min(this.gridGap, 0.05 * this.props.PanelWidth()));
+        return NumCast(this.layoutDoc._xMargin, 5);
     }
     @computed get yMargin() {
-        return this.props.yPadding || NumCast(this.layoutDoc._yMargin, 5);
+        return NumCast(this.layoutDoc._yMargin, 5);
     }
     @computed get gridGap() {
         return NumCast(this.layoutDoc._gridGap, 10);
@@ -86,13 +87,13 @@ export class CollectionNoteTakingView extends CollectionSubView() {
     }
     // maxColWidth returns the maximum column width, which is slightly less than the total available space.
     @computed get maxColWidth() {
-        return this.props.PanelWidth() - 2 * this.xMargin;
+        return this.props.PanelWidth();
     }
     // 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.numGroupColumns - 1;
-        return this.maxColWidth - numDividers * this.dividerWidth;
+        return this.maxColWidth - numDividers * this.DividerWidth;
     }
 
     // children is passed as a prop to the NoteTakingField, which uses this function
@@ -295,12 +296,9 @@ export class CollectionNoteTakingView extends CollectionSubView() {
         const heading = !d[this.notetakingCategoryField] ? 'unset' : Field.toString(d[this.notetakingCategoryField] as Field);
         const existingHeader = this.columnHeaders.find(sh => sh.heading === heading);
         const existingWidth = existingHeader?.width ? existingHeader.width : 0;
-        const maxWidth = existingWidth > 0 ? existingWidth * this.availableWidth - 2 * this.xMargin : this.maxColWidth - 2 * this.xMargin;
-        if (d.type === DocumentType.RTF) {
-            return maxWidth;
-        }
-        const width = d[WidthSym]();
-        return width < maxWidth ? width : maxWidth;
+        const maxWidth = existingWidth > 0 ? existingWidth * this.availableWidth : this.maxColWidth;
+        const width = d.fitWidth ? maxWidth : d[WidthSym]();
+        return Math.min(maxWidth - CollectionNoteTakingViewColumn.ColumnMargin, width < maxWidth ? width : maxWidth);
     }
 
     // how to get the height of a document. Nothing special here.
@@ -312,8 +310,6 @@ export class CollectionNoteTakingView extends CollectionSubView() {
         const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[WidthSym]() : 0);
         const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[HeightSym]() : 0);
         if (nw && nh) {
-            // const colWid = this.columnWidth / this.numGroupColumns;
-            // const docWid = this.layoutDoc._columnsFill ? colWid : Math.min(this.getDocWidth(d), colWid);
             const docWid = this.getDocWidth(d);
             return Math.min(maxHeight, (docWid * nh) / nw);
         }
@@ -390,7 +386,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
         let colStartXCoord = 0;
         for (let i = 0; i < numColumns; i++) {
             coords.push(colStartXCoord);
-            colStartXCoord += this.columnHeaders[i].width * this.availableWidth + this.dividerWidth;
+            colStartXCoord += this.columnHeaders[i].width * this.availableWidth + this.DividerWidth;
         }
         coords.push(this.PanelWidth);
         for (let i = 0; i < numColumns; i++) {
@@ -543,7 +539,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
                 numGroupColumns={this.numGroupColumns}
                 gridGap={this.gridGap}
                 pivotField={this.notetakingCategoryField}
-                dividerWidth={this.dividerWidth}
+                dividerWidth={this.DividerWidth}
                 maxColWidth={this.maxColWidth}
                 availableWidth={this.availableWidth}
                 PanelWidth={this.PanelWidth}
@@ -576,7 +572,9 @@ export class CollectionNoteTakingView extends CollectionSubView() {
         }
         const columnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null);
         const newColWidth = 1 / (this.numGroupColumns + 1);
-        return value && columnHeaders?.push(new SchemaHeaderField(value, undefined, undefined, newColWidth)) && this.resizeColumns(true, newColWidth, this.columnHeaders.length - 1) ? true : false;
+        value && columnHeaders?.push(new SchemaHeaderField(value, undefined, undefined, newColWidth)) && this.resizeColumns(true, newColWidth, this.columnHeaders.length - 1);
+        this.dataDoc.columnHeaders = new List<SchemaHeaderField>(columnHeaders.map(header => header[Copy]()));
+        return true;
     };
 
     onContextMenu = (e: React.MouseEvent): void => {
@@ -621,10 +619,10 @@ export class CollectionNoteTakingView extends CollectionSubView() {
     @computed get buttonMenu() {
         const menuDoc: Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null);
         if (menuDoc) {
-            const width: number = NumCast(menuDoc._width, 30);
-            const height: number = NumCast(menuDoc._height, 30);
+            const width = NumCast(menuDoc._width, 30);
+            const height = NumCast(menuDoc._height, 30);
             return (
-                <div className="buttonMenu-docBtn" style={{ width: width, height: height }}>
+                <div className="buttonMenu-docBtn" style={{ width, height }}>
                     <DocumentView
                         Document={menuDoc}
                         DataDoc={menuDoc}
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index c57677683..d951454ff 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -22,11 +22,6 @@ import { ContextMenuProps } from '../ContextMenuItem';
 import { EditableView } from '../EditableView';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
 import './CollectionNoteTakingView.scss';
-import { List } from '../../../fields/List';
-import { Field } from '../../util/ProsemirrorCopy/prompt';
-const higflyout = require('@hig/flyout');
-export const { anchorPoints } = higflyout;
-export const Flyout = higflyout.default;
 
 interface CSVFieldColumnProps {
     Document: Doc;
@@ -66,19 +61,15 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
 
     // columnWidth returns the width of a column in absolute pixels
     @computed get columnWidth() {
-        if (!this.props.columnHeaders || !this.props.headingObject) {
-            return this.props.maxColWidth;
-        }
-        if (this.props.columnHeaders.length == 1) {
-            return this.props.maxColWidth;
-        }
+        if (!this.props.columnHeaders || !this.props.headingObject || this.props.columnHeaders.length === 1) return '100%';
         const i = this.props.columnHeaders.indexOf(this.props.headingObject);
-        return this.props.columnHeaders[i].width * this.props.availableWidth;
+        return this.props.columnHeaders[i].width * 100 + '%';
     }
 
     private dropDisposer?: DragManager.DragDropDisposer;
     private _headerRef: React.RefObject<HTMLDivElement> = React.createRef();
 
+    public static ColumnMargin = 10;
     @observable _heading = this.props.headingObject ? this.props.headingObject.heading : this.props.heading;
     @observable _color = this.props.headingObject ? this.props.headingObject.color : '#f1efeb';
     _ele: HTMLElement | null = null;
@@ -153,14 +144,14 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
         const acolumnHeaders = Cast(this.props.Document.columnHeaders, listSpec(SchemaHeaderField), null);
         if (acolumnHeaders && this.props.headingObject) {
             const index = acolumnHeaders.indexOf(this.props.headingObject);
-            const columnHeaders = new List<SchemaHeaderField>(acolumnHeaders.map(header => header[Copy]())); // needed for undo to work properly.  otherwise we end up changing field values in the undo stack since they are shared by reference
+            const columnHeaders = acolumnHeaders; // new List<SchemaHeaderField>(acolumnHeaders.map(header => header[Copy]())); // needed for undo to work properly.  otherwise we end up changing field values in the undo stack since they are shared by reference
             const newColIndex = index > 0 ? index - 1 : 1;
             const newColHeader = this.props.columnHeaders ? this.props.columnHeaders[newColIndex] : undefined;
             const newHeading = newColHeader ? newColHeader.heading : 'unset';
             this.props.docList.forEach(d => (d[this.props.pivotField] = newHeading));
             const colWidth = this.props.columnHeaders ? this.props.columnHeaders[index].width : 0;
             columnHeaders.splice(index, 1);
-            Doc.GetProto(this.props.Document).columnHeaders = columnHeaders;
+            //Doc.GetProto(this.props.Document).columnHeaders = columnHeaders;
             this.props.resizeColumns(false, colWidth, index);
         }
     };
@@ -251,9 +242,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
                 ref={this._headerRef}
                 style={{
                     marginTop: 2 * this.props.yMargin,
-                    // width: (this.props.columnWidth) /
-                    //     ((uniqueHeadings.length) || 1)
-                    width: this.columnWidth - 20,
+                    width: 'calc(100% - 5px)',
                 }}>
                 <div
                     className="collectionNoteTakingView-sectionHeader-subCont"
@@ -261,48 +250,46 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
                     style={{ background: evContents !== `No Value` ? this._color : 'inherit' }}>
                     <EditableView GetValue={() => evContents} SetValue={this.headingChanged} contents={evContents} oneLine={true} />
                 </div>
+                {(this.props.columnHeaders?.length ?? 0) > 1 && (
+                    <button className="collectionNoteTakingView-sectionDelete" onClick={this.deleteColumn}>
+                        <FontAwesomeIcon icon="trash" size="lg" />
+                    </button>
+                )}
             </div>
         ) : null;
-        const templatecols = `${this.columnWidth}px `;
+        const templatecols = this.columnWidth;
         const type = this.props.Document.type;
         return (
             <>
                 {headingView}
-                {
-                    <div style={{ height: '100%' }}>
-                        <div
-                            key={`${heading}-stack`}
-                            className={`collectionNoteTakingView-Nodes`}
-                            style={{
-                                padding: `${columnYMargin}px ${0}px ${this.props.yMargin}px ${0}px`,
-                                margin: 'auto',
-                                width: 'max-content', //singleColumn ? undefined : `${cols * (style.columnWidth + style.gridGap) + 2 * style.xMargin - style.gridGap}px`,
-                                height: 'max-content',
-                                position: 'relative',
-                                gridGap: this.props.gridGap,
-                                gridTemplateColumns: templatecols,
-                                gridAutoRows: '0px',
-                            }}>
-                            {this.props.renderChildren(this.props.docList)}
-                        </div>
+                <div style={{ height: '100%' }}>
+                    <div
+                        key={`${heading}-stack`}
+                        className={`collectionNoteTakingView-Nodes`}
+                        style={{
+                            padding: `${columnYMargin}px ${0}px ${this.props.yMargin}px ${0}px`,
+                            margin: 'auto',
+                            width: 'max-content',
+                            height: 'max-content',
+                            position: 'relative',
+                            gridGap: this.props.gridGap,
+                            gridTemplateColumns: templatecols,
+                            gridAutoRows: '0px',
+                        }}>
+                        {this.props.renderChildren(this.props.docList)}
+                    </div>
 
-                        {!this.props.chromeHidden && type !== DocumentType.PRES ? (
-                            <div className="collectionNoteTakingView-DocumentButtons" style={{ width: this.columnWidth - 20, marginBottom: 10 }}>
-                                <div key={`${heading}-add-document`} className="collectionNoteTakingView-addDocumentButton">
-                                    <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} textCallback={this.textCallback} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} />
-                                </div>
-                                <div key={`${this.props.Document[Id]}-addGroup`} className="collectionNoteTakingView-addDocumentButton">
-                                    <EditableView {...this.props.editableViewProps()} />
-                                </div>
-                                {this.props.columnHeaders?.length && this.props.columnHeaders.length > 1 && (
-                                    <button className="collectionNoteTakingView-sectionDelete" onClick={this.deleteColumn}>
-                                        <FontAwesomeIcon icon="trash" size="lg" />
-                                    </button>
-                                )}
+                    {!this.props.chromeHidden && type !== DocumentType.PRES ? (
+                        <div className="collectionNoteTakingView-DocumentButtons" style={{ marginBottom: 10 }}>
+                            <div key={`${heading}-add-document`} className="collectionNoteTakingView-addDocumentButton">
+                                <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} textCallback={this.textCallback} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} />
                             </div>
-                        ) : null}
-                    </div>
-                }
+                            <div key={`${this.props.Document[Id]}-addGroup`} className="collectionNoteTakingView-addDocumentButton">
+                                <EditableView {...this.props.editableViewProps()} />
+                            </div>
+                        </div>
+                    ) : null}
+                </div>
             </>
         );
     }
diff --git a/src/client/views/collections/CollectionNoteTakingViewDivider.tsx b/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
index 8d659f790..a1309b11f 100644
--- a/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewDivider.tsx
@@ -57,7 +57,6 @@ export class CollectionNoteTakingViewDivider extends React.Component<DividerProp
                         width: 12,
                         borderRight: '4px solid #282828',
                         borderLeft: '4px solid #282828',
-                        margin: '0px 10px',
                     }}
                 />
             </div>
-- 
cgit v1.2.3-70-g09d2


From dff4b18106261af77d81211e5482a38b19b2a166 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 26 Aug 2022 09:19:15 -0400
Subject: more notetaking cleanup

---
 src/client/views/collections/CollectionNoteTakingView.scss   | 12 +++++++++++-
 .../views/collections/CollectionNoteTakingViewColumn.tsx     |  7 +------
 2 files changed, 12 insertions(+), 7 deletions(-)

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

diff --git a/src/client/views/collections/CollectionNoteTakingView.scss b/src/client/views/collections/CollectionNoteTakingView.scss
index 5582fd391..08b13fd50 100644
--- a/src/client/views/collections/CollectionNoteTakingView.scss
+++ b/src/client/views/collections/CollectionNoteTakingView.scss
@@ -54,7 +54,7 @@
 .collectionNoteTakingViewFieldColumn {
     height: 100%;
     display: flex;
-    flex-direction: colum;
+    overflow: hidden;
 }
 .collectionNoteTakingViewFieldColumn:hover {
     .collectionNoteTakingView-DocumentButtons {
@@ -112,6 +112,11 @@
         height: auto;
     }
 
+    .collectionNoteTakingView-columnStack {
+        height: 100%;
+        width: 100%;
+        display: inline-block;
+    }
     .collectionNoteTakingView-Nodes {
         width: 100%;
         height: 100%;
@@ -123,6 +128,11 @@
         left: 0;
         width: 100%;
         position: absolute;
+        margin: auto;
+        width: max-content;
+        height: max-content;
+        position: relative;
+        grid-auto-rows: 0px;
     }
 
     .collectionNoteTakingView-description {
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index d951454ff..84d1c0205 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -262,19 +262,14 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu
         return (
             <>
                 {headingView}
-                <div style={{ height: '100%' }}>
+                <div className="collectionNoteTakingView-columnStack">
                     <div
                         key={`${heading}-stack`}
                         className={`collectionNoteTakingView-Nodes`}
                         style={{
                             padding: `${columnYMargin}px ${0}px ${this.props.yMargin}px ${0}px`,
-                            margin: 'auto',
-                            width: 'max-content',
-                            height: 'max-content',
-                            position: 'relative',
                             gridGap: this.props.gridGap,
                             gridTemplateColumns: templatecols,
-                            gridAutoRows: '0px',
                         }}>
                         {this.props.renderChildren(this.props.docList)}
                     </div>
-- 
cgit v1.2.3-70-g09d2

