From 3c8cb517c811f94dce1e3d8430e07af316642365 Mon Sep 17 00:00:00 2001
From: sotech117 <michael_foiani@brown.edu>
Date: Thu, 13 Apr 2023 05:39:21 -0400
Subject: Compile and make compatible all the scattered code I had for
 empowering trails for dash meeting. Still much to do with ui, but basic
 functionaltiy is there. Two key things, 1) navigation for branching trails,
 and 2) ability to runSubroutines on tested trails.

---
 src/client/views/collections/TreeView.tsx | 51 +++++++++++++++++++++++++++++--
 1 file changed, 49 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 75e76019e..153c2c71a 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -227,6 +227,37 @@ export class TreeView extends React.Component<TreeViewProps> {
         }
     };
 
+    @undoBatch
+    @action
+    recurToggle = (childList: Doc[]) => {
+        if (childList.length > 0) {
+            childList.forEach(child => {
+                console.log(child);
+                child.runProcess = !!!child.runProcess;
+                child.toggleChildrenRun?.();
+            });
+        }
+    };
+
+    @undoBatch
+    @action
+    getRunningChildren = (childList: Doc[]) => {
+        if (childList.length === 0) {
+            return [];
+        }
+
+        const runningChildren = [];
+        childList.forEach(child => {
+            if (child.runProcess && child.getChildrenToRun) {
+                if (child.runProcess) {
+                    runningChildren.push(child);
+                }
+                runningChildren.push(...(child.getChildrenToRun?.() ?? []));
+            }
+        });
+        return runningChildren;
+    };
+
     constructor(props: any) {
         super(props);
         if (!TreeView._openLevelScript) {
@@ -235,6 +266,18 @@ export class TreeView extends React.Component<TreeViewProps> {
         }
         this._openScript = Doc.IsSystem(this.props.document) ? undefined : () => TreeView._openLevelScript!;
         this._editTitleScript = Doc.IsSystem(this.props.document) ? () => TreeView._openLevelScript! : () => TreeView._openTitleScript!;
+
+        // set for child processing highligting
+        // this.dataDoc.testing = 'testing';
+        this.dataDoc.hasChildren = this.childDocs.length > 0;
+        // this.dataDoc.children = this.childDocs;
+        this.dataDoc.toggleChildrenRun = () => {
+            this.recurToggle(this.childDocs);
+        };
+
+        this.dataDoc.getChildrenToRun = () => {
+            return this.getRunningChildren(this.childDocs);
+        };
     }
 
     _treeEle: any;
@@ -696,7 +739,11 @@ export class TreeView extends React.Component<TreeViewProps> {
                 ) : (
                     <div className="treeView-bulletIcons" style={{ color: Doc.IsSystem(DocCast(this.doc.proto)) ? 'red' : undefined }}>
                         <div className={`treeView-${this.onCheckedClick ? 'checkIcon' : 'expandIcon'}`}>
-                            <FontAwesomeIcon size="sm" icon={checked === 'check' ? 'check' : checked === 'x' ? 'times' : checked === 'unchecked' ? 'square' : !this.treeViewOpen ? 'caret-right' : 'caret-down'} />
+                            <FontAwesomeIcon
+                                size="sm"
+                                style={{ display: this.childDocs?.length >= 1 ? 'block' : 'none' }}
+                                icon={checked === 'check' ? 'check' : checked === 'x' ? 'times' : checked === 'unchecked' ? 'square' : !this.treeViewOpen ? 'caret-right' : 'caret-down'}
+                            />
                         </div>
                         {this.onCheckedClick ? null : typeof iconType === 'string' ? <FontAwesomeIcon icon={iconType as IconProp} /> : iconType}
                     </div>
@@ -899,7 +946,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 })}
                 Document={this.doc}
                 fitWidth={returnTrue}
-                DataDoc={undefined}
+                DataDoc={this.dataDoc}
                 scriptContext={this}
                 hideDecorationTitle={this.props.treeView.outlineMode}
                 hideResizeHandles={this.props.treeView.outlineMode}
-- 
cgit v1.2.3-70-g09d2


From 5651f5428f8464ae0f131c73601b69aba11dff98 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 31 Aug 2023 12:36:33 -0400
Subject: fixed properties view text colors

---
 src/client/views/MainView.tsx             | 2 +-
 src/client/views/collections/TreeView.tsx | 3 ---
 src/client/views/nodes/trails/PresBox.tsx | 2 +-
 3 files changed, 2 insertions(+), 5 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 01a26559c..7ae9a374d 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -809,7 +809,7 @@ export class MainView extends React.Component {
                                 <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={SettingsManager.userColor} size="sm" />
                             </div>
                         )}
-                        <div className="properties-container" style={{ width: this.propertiesWidth() }}>
+                        <div className="properties-container" style={{ width: this.propertiesWidth(), color: SettingsManager.userColor }}>
                             {this.propertiesWidth() < 10 ? null : <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={DocumentViewInternal.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />}
                         </div>
                     </div>
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 4f9310434..8dd1c8ee8 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -227,7 +227,6 @@ export class TreeView extends React.Component<TreeViewProps> {
     recurToggle = (childList: Doc[]) => {
         if (childList.length > 0) {
             childList.forEach(child => {
-                console.log(child);
                 child.runProcess = !!!child.runProcess;
                 TreeView.ToggleChildrenRun.get(child)?.();
             });
@@ -265,8 +264,6 @@ export class TreeView extends React.Component<TreeViewProps> {
         this._editTitleScript = Doc.IsSystem(this.props.document) ? () => TreeView._openLevelScript! : () => TreeView._openTitleScript!;
 
         // set for child processing highligting
-        // this.dataDoc.testing = 'testing';
-        console.log(this.doc, this.dataDoc, this.childDocs);
         this.dataDoc.hasChildren = this.childDocs.length > 0;
         // this.dataDoc.children = this.childDocs;
         TreeView.ToggleChildrenRun.set(this.doc, () => {
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 7bb1b80a3..92c130ea1 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -1691,7 +1691,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             </div>
         );
         const presDirection = (direction: PresEffectDirection, icon: string, gridColumn: number, gridRow: number, opts: object) => {
-            const color = activeItem.presentation_effectDirection === direction || (direction === PresEffectDirection.Center && !activeItem.presentation_effectDirection) ? Colors.LIGHT_BLUE : 'black';
+            const color = activeItem.presentation_effectDirection === direction || (direction === PresEffectDirection.Center && !activeItem.presentation_effectDirection) ? SettingsManager.userVariantColor : SettingsManager.userColor;
             return (
                 <Tooltip title={<div className="dash-tooltip">{direction}</div>}>
                     <div
-- 
cgit v1.2.3-70-g09d2


From ff458c1cc2619803b8f8ba6e1a2b713b8d3bafe7 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 5 Sep 2023 11:29:05 -0400
Subject: changed tree view drag behavior

---
 src/client/views/collections/TreeView.tsx | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

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

diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 8dd1c8ee8..f1268119e 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -332,7 +332,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         const pt = [e.clientX, e.clientY];
         const rect = this._header.current!.getBoundingClientRect();
         const before = pt[1] < rect.top + rect.height / 2;
-        const inside = pt[0] > Math.min(rect.left + 75, rect.left + rect.width * 0.75) || (!before && this.treeViewOpen && this.childDocs?.length);
+        const inside = pt[0] > rect.left + rect.width * 0.33 || (!before && this.treeViewOpen && this.childDocs?.length);
         this._header.current!.className = 'treeView-header';
         if (!this.props.treeView.outlineMode || DragManager.DocDragData?.treeViewDoc === this.props.treeView.rootDoc) {
             if (inside) this._header.current!.className += ' treeView-header-inside';
@@ -392,7 +392,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         if (!this._header.current) return false;
         const rect = this._header.current.getBoundingClientRect();
         const before = pt[1] < rect.top + rect.height / 2;
-        const inside = this.props.treeView.fileSysMode && !this.doc.isFolder ? false : pt[0] > Math.min(rect.left + 75, rect.left + rect.width * 0.75) || (!before && this.treeViewOpen && this.childDocs?.length ? true : false);
+        const inside = this.props.treeView.fileSysMode && !this.doc.isFolder ? false : pt[0] > rect.left + rect.width * 0.33 || (!before && this.treeViewOpen && this.childDocs?.length ? true : false);
         if (de.complete.linkDragData) {
             const sourceDoc = de.complete.linkDragData.linkSourceGetAnchor();
             const destDoc = this.doc;
@@ -1140,7 +1140,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         const pt = [de.clientX, de.clientY];
         const rect = this._header.current!.getBoundingClientRect();
         const before = pt[1] < rect.top + rect.height / 2;
-        const inside = this.props.treeView.fileSysMode && !this.doc.isFolder ? false : pt[0] > Math.min(rect.left + 75, rect.left + rect.width * 0.75) || (!before && this.treeViewOpen && this.childDocs?.length ? true : false);
+        const inside = this.props.treeView.fileSysMode && !this.doc.isFolder ? false : pt[0] > rect.left + rect.width * 0.33 || (!before && this.treeViewOpen && this.childDocs?.length ? true : false);
 
         const docs = this.props.treeView.onTreeDrop(de, (docs: Doc[]) => this.dropDocuments(docs, before, inside, 'copy', undefined, undefined, false));
     };
-- 
cgit v1.2.3-70-g09d2


From 3a048ae3acbbf63611bfbb7cded772fc3decd526 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 11 Sep 2023 22:58:56 -0400
Subject: usercolor cleanup

---
 src/client/util/RTFMarkup.tsx                      |  2 +-
 src/client/views/AntimodeMenu.tsx                  |  7 +-
 src/client/views/ContextMenu.tsx                   |  7 +-
 src/client/views/PropertiesButtons.tsx             |  5 +-
 src/client/views/PropertiesSection.tsx             |  7 +-
 src/client/views/PropertiesView.tsx                | 21 +++---
 src/client/views/StyleProvider.tsx                 |  8 +--
 src/client/views/collections/CollectionMenu.tsx    |  6 +-
 .../views/collections/CollectionStackingView.tsx   |  3 +-
 src/client/views/collections/TreeView.tsx          |  5 +-
 .../collectionFreeForm/MarqueeOptionsMenu.tsx      | 38 ++---------
 src/client/views/nodes/MapBox/MapAnchorMenu.tsx    | 75 +++++++++++-----------
 src/client/views/nodes/MapBox/MapBox.tsx           |  3 +-
 13 files changed, 82 insertions(+), 105 deletions(-)

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

diff --git a/src/client/util/RTFMarkup.tsx b/src/client/util/RTFMarkup.tsx
index 9dd14a3c3..c8940194c 100644
--- a/src/client/util/RTFMarkup.tsx
+++ b/src/client/util/RTFMarkup.tsx
@@ -137,7 +137,7 @@ export class RTFMarkup extends React.Component<{}> {
     render() {
         return (
             <MainViewModal
-                dialogueBoxStyle={{ backgroundColor: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor), padding: '16px' }}
+                dialogueBoxStyle={{ backgroundColor: SettingsManager.userBackgroundColor, color: SettingsManager.userColor, padding: '16px' }}
                 contents={this.cheatSheet}
                 isDisplayed={this.isOpen}
                 interactive={true}
diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx
index c41ea7053..16e76694d 100644
--- a/src/client/views/AntimodeMenu.tsx
+++ b/src/client/views/AntimodeMenu.tsx
@@ -3,6 +3,7 @@ import { observable, action, runInAction } from 'mobx';
 import './AntimodeMenu.scss';
 import { StrCast } from '../../fields/Types';
 import { Doc } from '../../fields/Doc';
+import { SettingsManager } from '../util/SettingsManager';
 export interface AntimodeMenuProps {}
 
 /**
@@ -150,7 +151,7 @@ export abstract class AntimodeMenu<T extends AntimodeMenuProps> extends React.Co
                     left: this._left,
                     top: this._top,
                     opacity: this._opacity,
-                    background: StrCast(Doc.UserDoc().userBackgroundColor),
+                    background: SettingsManager.userBackgroundColor,
                     transitionProperty: this._transitionProperty,
                     transitionDuration: this._transitionDuration,
                     transitionDelay: this._transitionDelay,
@@ -176,7 +177,7 @@ export abstract class AntimodeMenu<T extends AntimodeMenuProps> extends React.Co
                     height: 'inherit',
                     width: 200,
                     opacity: this._opacity,
-                    background: StrCast(Doc.UserDoc().userBackgroundColor),
+                    background: SettingsManager.userBackgroundColor,
                     transitionProperty: this._transitionProperty,
                     transitionDuration: this._transitionDuration,
                     transitionDelay: this._transitionDelay,
@@ -199,7 +200,7 @@ export abstract class AntimodeMenu<T extends AntimodeMenuProps> extends React.Co
                     left: this._left,
                     top: this._top,
                     opacity: this._opacity,
-                    background: StrCast(Doc.UserDoc().userBackgroundColor),
+                    background: SettingsManager.userBackgroundColor,
                     transitionProperty: this._transitionProperty,
                     transitionDuration: this._transitionDuration,
                     transitionDelay: this._transitionDelay,
diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index 8412a9aae..adefc7e9c 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -7,6 +7,7 @@ import { ContextMenuItem, ContextMenuProps, OriginalMenuProps } from './ContextM
 import { Utils } from '../../Utils';
 import { StrCast } from '../../fields/Types';
 import { Doc } from '../../fields/Doc';
+import { SettingsManager } from '../util/SettingsManager';
 
 @observer
 export class ContextMenu extends React.Component {
@@ -195,7 +196,7 @@ export class ContextMenu extends React.Component {
                 <div
                     className="contextMenu-group"
                     style={{
-                        background: StrCast(Doc.UserDoc().userVariantColor),
+                        background: StrCast(SettingsManager.userVariantColor),
                     }}>
                     <div className="contextMenu-description">{value.join(' -> ')}</div>
                 </div>
@@ -222,8 +223,8 @@ export class ContextMenu extends React.Component {
                 style={{
                     left: this.pageX,
                     ...(this._yRelativeToTop ? { top: this.pageY } : { bottom: this.pageY }),
-                    background: StrCast(Doc.UserDoc().userBackgroundColor),
-                    color: StrCast(Doc.UserDoc().userColor),
+                    background: SettingsManager.userBackgroundColor,
+                    color: SettingsManager.userColor,
                 }}>
                 {!this.itemsNeedSearch ? null : (
                     <span className={'search-icon'}>
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 8b2b77aca..40d42a4de 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -32,6 +32,7 @@ import { TfiBarChart } from 'react-icons/tfi';
 import { CiGrid31 } from 'react-icons/ci';
 import { RxWidth } from 'react-icons/rx';
 import { Dropdown, DropdownType, IListItemProps, Toggle, ToggleType, Type } from 'browndash-components';
+import { SettingsManager } from '../util/SettingsManager';
 
 enum UtilityButtonState {
     Default,
@@ -57,7 +58,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             <Toggle
                 toggleStatus={BoolCast(targetDoc[property])}
                 text={label(targetDoc?.[property])}
-                color={StrCast(Doc.UserDoc().userColor)}
+                color={SettingsManager.userColor}
                 icon={icon(targetDoc?.[property] as any)}
                 iconPlacement={'left'}
                 align={'flex-start'}
@@ -380,7 +381,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
                 selectedVal={this.onClickVal}
                 setSelectedVal={val => this.handleOptionChange(val as string)}
                 title={'Choose onClick behaviour'}
-                color={StrCast(Doc.UserDoc().userColor)}
+                color={SettingsManager.userColor}
                 dropdownType={DropdownType.SELECT}
                 type={Type.SEC}
                 fillWidth
diff --git a/src/client/views/PropertiesSection.tsx b/src/client/views/PropertiesSection.tsx
index 0e7cd7e92..bd586b2f9 100644
--- a/src/client/views/PropertiesSection.tsx
+++ b/src/client/views/PropertiesSection.tsx
@@ -5,6 +5,7 @@ import { observer } from 'mobx-react';
 import './PropertiesSection.scss';
 import { Doc } from '../../fields/Doc';
 import { StrCast } from '../../fields/Types';
+import { SettingsManager } from '../util/SettingsManager';
 
 export interface PropertiesSectionProps {
     title: string;
@@ -19,15 +20,15 @@ export interface PropertiesSectionProps {
 @observer
 export class PropertiesSection extends React.Component<PropertiesSectionProps> {
     @computed get color() {
-        return StrCast(Doc.UserDoc().userColor);
+        return SettingsManager.userColor;
     }
 
     @computed get backgroundColor() {
-        return StrCast(Doc.UserDoc().userBackgroundColor);
+        return SettingsManager.userBackgroundColor;
     }
 
     @computed get variantColor() {
-        return StrCast(Doc.UserDoc().userVariantColor);
+        return SettingsManager.userVariantColor;
     }
 
     @observable isDouble: boolean = false;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index b25ac7903..699aafe80 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -368,7 +368,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 <IconButton
                     icon={<FontAwesomeIcon icon={'ellipsis-h'} />}
                     size={Size.XSMALL}
-                    color={StrCast(Doc.UserDoc().userColor)}
+                    color={SettingsManager.userColor}
                     onClick={action(() => {
                         if (this.selectedDocumentView || this.selectedDoc) {
                             SharingManager.Instance.open(this.selectedDocumentView?.props.Document === this.selectedDoc ? this.selectedDocumentView : undefined, this.selectedDoc);
@@ -518,7 +518,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 <div>
                     <br></br> Individuals with Access to this Document
                 </div>
-                <div className="propertiesView-sharingTable" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor) }}>
+                <div className="propertiesView-sharingTable" style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }}>
                     {<div> {individualTableEntries}</div>}
                 </div>
                 {groupTableEntries.length > 0 ? (
@@ -526,7 +526,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                         <div>
                             <br></br> Groups with Access to this Document
                         </div>
-                        <div className="propertiesView-sharingTable" style={{ background: StrCast(Doc.UserDoc().userBackgroundColor), color: StrCast(Doc.UserDoc().userColor) }}>
+                        <div className="propertiesView-sharingTable" style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor }}>
                             {<div> {groupTableEntries}</div>}
                         </div>
                     </div>
@@ -546,15 +546,15 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     toggleCheckbox = () => (this.layoutFields = !this.layoutFields);
 
     @computed get color() {
-        return StrCast(Doc.UserDoc().userColor);
+        return SettingsManager.userColor;
     }
 
     @computed get backgroundColor() {
-        return StrCast(Doc.UserDoc().userBackgroundColor);
+        return SettingsManager.userBackgroundColor;
     }
 
     @computed get variantColor() {
-        return StrCast(Doc.UserDoc().userVariantColor);
+        return SettingsManager.userVariantColor;
     }
 
     @computed get editableTitle() {
@@ -585,8 +585,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @computed get currentType() {
-        // console.log("current type " + this.selectedDoc?.type)
-
         const documentType = StrCast(this.selectedDoc?.type);
         var currentType: string = documentType;
         var capitalizedDocType = Utils.cleanDocumentType(currentType as DocumentType);
@@ -610,9 +608,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         if (iconName) {
             const Icon = Icons[iconName as keyof typeof Icons];
             return <Icon />;
-        } else {
-            return <Icons.BsFillCollectionFill />;
         }
+        return <Icons.BsFillCollectionFill />;
     }
 
     @undoBatch
@@ -1683,8 +1680,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                     <div
                         className="propertiesView"
                         style={{
-                            background: StrCast(Doc.UserDoc().userBackgroundColor),
-                            color: StrCast(Doc.UserDoc().userColor),
+                            background: SettingsManager.userBackgroundColor,
+                            color: SettingsManager.userColor,
                             width: this.props.width,
                             minWidth: this.props.width,
                         }}>
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 8a5ad3139..85aa5ad83 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -162,8 +162,8 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             );
         case StyleProp.Color:
             if (DocumentView.LastPressedSidebarBtn === doc) return SettingsManager.userBackgroundColor;
-            if (Doc.IsSystem(doc!)) return StrCast(Doc.UserDoc().userColor)
-            if (doc?.type === DocumentType.FONTICON) return Doc.UserDoc().userColor;
+            if (Doc.IsSystem(doc!)) return SettingsManager.userColor;
+            if (doc?.type === DocumentType.FONTICON) return SettingsManager.userColor;
             const docColor: Opt<string> = StrCast(doc?.[fieldKey + 'color'], StrCast(doc?._color));
             if (docColor) return docColor;
             const docView = props?.DocumentView?.();
@@ -196,7 +196,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                 ? 15
                 : 0;
         case StyleProp.BackgroundColor: {
-            if (DocumentView.LastPressedSidebarBtn === doc) return StrCast(Doc.UserDoc().userColor); // hack to indicate active menu panel item
+            if (DocumentView.LastPressedSidebarBtn === doc) return SettingsManager.userColor; // hack to indicate active menu panel item
             let docColor: Opt<string> = StrCast(doc?.[fieldKey + '_backgroundColor'], StrCast(doc?._backgroundColor, isCaption ? 'rgba(0,0,0,0.4)' : ''));
             // prettier-ignore
             switch (doc?.type) {
@@ -350,7 +350,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
 }
 
 export function DashboardToggleButton(doc: Doc, field: string, onIcon: IconProp, offIcon: IconProp, clickFunc?: () => void) {
-    const color = StrCast(Doc.UserDoc().userColor);
+    const color = SettingsManager.userColor;
     return (
         <IconButton
             size={Size.XSMALL}
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 78ab0797b..ec9d86c1a 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -158,7 +158,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
                 <Toggle
                     toggleType={ToggleType.BUTTON}
                     type={Type.PRIM}
-                    color={StrCast(Doc.UserDoc().userColor)}
+                    color={SettingsManager.userColor}
                     onClick={this.toggleTopBar}
                     toggleStatus={SettingsManager.headerBarHeight > 0}
                     icon={<FontAwesomeIcon icon={headerIcon} size="lg" />}
@@ -167,7 +167,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
                 <Toggle
                     toggleType={ToggleType.BUTTON}
                     type={Type.PRIM}
-                    color={StrCast(Doc.UserDoc().userColor)}
+                    color={SettingsManager.userColor}
                     onClick={this.toggleProperties}
                     toggleStatus={SettingsManager.propertiesWidth > 0}
                     icon={<FontAwesomeIcon icon={propIcon} size="lg" />}
@@ -183,7 +183,7 @@ export class CollectionMenu extends AntimodeMenu<CollectionMenuProps> {
                 className="collectionMenu-container"
                 style={{
                     background: SettingsManager.userBackgroundColor,
-                    // borderColor: StrCast(Doc.UserDoc().userColor)
+                    // borderColor: SettingsManager.userColor
                 }}>
                 {this.contMenuButtons}
                 {hardCodedButtons}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index e4a0d6dad..9ba4cb6cf 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -31,6 +31,7 @@ import { CollectionMasonryViewFieldRow } from './CollectionMasonryViewFieldRow';
 import './CollectionStackingView.scss';
 import { CollectionStackingViewFieldColumn } from './CollectionStackingViewFieldColumn';
 import { CollectionSubView } from './CollectionSubView';
+import { SettingsManager } from '../../util/SettingsManager';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 export type collectionStackingViewProps = {
@@ -426,7 +427,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
                 className="collectionStackingView-columnDragger"
                 onPointerDown={this.columnDividerDown}
                 ref={this._draggerRef}
-                style={{ cursor: this._cursor, color: StrCast(Doc.UserDoc().userColor), left: `${this.columnWidth + this.xMargin}px`, top: `${Math.max(0, this.yMargin - 9)}px` }}>
+                style={{ cursor: this._cursor, color: SettingsManager.userColor, left: `${this.columnWidth + this.xMargin}px`, top: `${Math.max(0, this.yMargin - 9)}px` }}>
                 <FontAwesomeIcon icon={'arrows-alt-h'} />
             </div>
         );
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index f1268119e..71e9f4dfa 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -36,6 +36,7 @@ import './TreeView.scss';
 import React = require('react');
 import { IconButton, Size } from 'browndash-components';
 import { TreeSort } from './TreeSort';
+import { SettingsManager } from '../../util/SettingsManager';
 
 export interface TreeViewProps {
     treeView: CollectionTreeView;
@@ -736,7 +737,7 @@ export class TreeView extends React.Component<TreeViewProps> {
     @computed get renderBullet() {
         TraceMobx();
         const iconType = this.props.treeView.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ':open' : !this.childDocs.length ? ':empty' : '')) || 'question';
-        const color = StrCast(Doc.UserDoc().userColor);
+        const color = SettingsManager.userColor;
         const checked = this.onCheckedClick ? this.doc.treeView_Checked ?? 'unchecked' : undefined;
         return (
             <div
@@ -796,7 +797,7 @@ export class TreeView extends React.Component<TreeViewProps> {
     @observable headerEleWidth = 0;
     @computed get titleButtons() {
         const customHeaderButtons = this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.Decorations);
-        const color = StrCast(Doc.UserDoc().userColor);
+        const color = SettingsManager.userColor;
         return this.props.treeViewHideHeaderFields() || this.doc.treeView_HideHeaderFields ? null : (
             <>
                 {customHeaderButtons} {/* e.g.,. hide button is set by dashboardStyleProvider */}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
index 71900c63f..607f9fb95 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx
@@ -8,6 +8,7 @@ import { IconButton } from 'browndash-components';
 import { StrCast } from '../../../../fields/Types';
 import { Doc } from '../../../../fields/Doc';
 import { computed } from 'mobx';
+import { SettingsManager } from '../../../util/SettingsManager';
 
 @observer
 export class MarqueeOptionsMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -27,43 +28,18 @@ export class MarqueeOptionsMenu extends AntimodeMenu<AntimodeMenuProps> {
     }
 
     @computed get userColor() {
-        return StrCast(Doc.UserDoc().userColor)
+        return SettingsManager.userColor;
     }
 
     render() {
         const presPinWithViewIcon = <img src="/assets/pinWithView.png" style={{ width: 19 }} />;
         const buttons = (
             <>
-                <IconButton 
-                    tooltip={"Create a Collection"}
-                    onPointerDown={this.createCollection}
-                    icon={<FontAwesomeIcon icon="object-group"/>}
-                    color={this.userColor}
-                />
-                <IconButton 
-                    tooltip={"Create a Grouping"}
-                    onPointerDown={e => this.createCollection(e, true)}
-                    icon={<FontAwesomeIcon icon="layer-group"/>}
-                    color={this.userColor}
-                />
-                <IconButton 
-                    tooltip={"Summarize Documents"}
-                    onPointerDown={this.summarize}
-                    icon={<FontAwesomeIcon icon="compress-arrows-alt"/>}
-                    color={this.userColor}
-                />
-                <IconButton 
-                    tooltip={"Delete Documents"}
-                    onPointerDown={this.delete}
-                    icon={<FontAwesomeIcon icon="trash-alt"/>}
-                    color={this.userColor}
-                />
-                <IconButton 
-                    tooltip={"Pin selected region"}
-                    onPointerDown={this.pinWithView}
-                    icon={<FontAwesomeIcon icon="map-pin"/>}
-                    color={this.userColor}
-                />
+                <IconButton tooltip={'Create a Collection'} onPointerDown={this.createCollection} icon={<FontAwesomeIcon icon="object-group" />} color={this.userColor} />
+                <IconButton tooltip={'Create a Grouping'} onPointerDown={e => this.createCollection(e, true)} icon={<FontAwesomeIcon icon="layer-group" />} color={this.userColor} />
+                <IconButton tooltip={'Summarize Documents'} onPointerDown={this.summarize} icon={<FontAwesomeIcon icon="compress-arrows-alt" />} color={this.userColor} />
+                <IconButton tooltip={'Delete Documents'} onPointerDown={this.delete} icon={<FontAwesomeIcon icon="trash-alt" />} color={this.userColor} />
+                <IconButton tooltip={'Pin selected region'} onPointerDown={this.pinWithView} icon={<FontAwesomeIcon icon="map-pin" />} color={this.userColor} />
             </>
         );
         return this.getElement(buttons);
diff --git a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx
index f731763af..f0827936b 100644
--- a/src/client/views/nodes/MapBox/MapAnchorMenu.tsx
+++ b/src/client/views/nodes/MapBox/MapAnchorMenu.tsx
@@ -6,7 +6,7 @@ import { ColorState } from 'react-color';
 import { Doc, Opt } from '../../../../fields/Doc';
 import { returnFalse, setupMoveUpEvents, unimplementedFunction, Utils } from '../../../../Utils';
 import { SelectionManager } from '../../../util/SelectionManager';
-import { AntimodeMenu, AntimodeMenuProps } from "../../AntimodeMenu"
+import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu';
 import { LinkPopup } from '../../linking/LinkPopup';
 import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT';
 // import { GPTPopup, GPTPopupMode } from './../../GPTPopup/GPTPopup';
@@ -15,6 +15,7 @@ import './MapAnchorMenu.scss';
 import { ColorPicker, Group, IconButton, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components';
 import { StrCast } from '../../../../fields/Types';
 import { DocumentType } from '../../../documents/DocumentTypes';
+import { SettingsManager } from '../../../util/SettingsManager';
 
 @observer
 export class MapAnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -24,9 +25,6 @@ export class MapAnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
     private _disposer2: IReactionDisposer | undefined;
     private _commentCont = React.createRef<HTMLButtonElement>();
 
-
-
-
     public onMakeAnchor: () => Opt<Doc> = () => undefined; // Method to get anchor from text search
 
     public Center: () => void = unimplementedFunction;
@@ -90,41 +88,39 @@ export class MapAnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
     //     );
     // };
 
-
     static top = React.createRef<HTMLDivElement>();
     // public get Top(){
     //     return this.top
     // }
 
-
     render() {
-        const buttons =(
-                <>
-                    {(
-                        <IconButton
-                            tooltip="Delete Pin" //
-                            onPointerDown={this.Delete}
-                            icon={<FontAwesomeIcon icon="trash-alt" />}
-                            color={StrCast(Doc.UserDoc().userColor)}
-                        />
-                    )}
-                    {(
-                        <IconButton
-                            tooltip="Link Note to Pin" //
-                            onPointerDown={this.LinkNote}
-                            icon={<FontAwesomeIcon icon="sticky-note" />}
-                            color={StrCast(Doc.UserDoc().userColor)}
-                        />
-                    )}
-                    {(
-                        <IconButton
-                            tooltip="Center on pin" //
-                            onPointerDown={this.Center}
-                            icon={<FontAwesomeIcon icon="compress-arrows-alt" />}
-                            color={StrCast(Doc.UserDoc().userColor)}
-                        />
-                    )}
-                    {/* {this.IsTargetToggler !== returnFalse && (
+        const buttons = (
+            <>
+                {
+                    <IconButton
+                        tooltip="Delete Pin" //
+                        onPointerDown={this.Delete}
+                        icon={<FontAwesomeIcon icon="trash-alt" />}
+                        color={SettingsManager.userColor}
+                    />
+                }
+                {
+                    <IconButton
+                        tooltip="Link Note to Pin" //
+                        onPointerDown={this.LinkNote}
+                        icon={<FontAwesomeIcon icon="sticky-note" />}
+                        color={SettingsManager.userColor}
+                    />
+                }
+                {
+                    <IconButton
+                        tooltip="Center on pin" //
+                        onPointerDown={this.Center}
+                        icon={<FontAwesomeIcon icon="compress-arrows-alt" />}
+                        color={SettingsManager.userColor}
+                    />
+                }
+                {/* {this.IsTargetToggler !== returnFalse && (
                         <Toggle
                             tooltip={'Make target visibility toggle on click'}
                             type={Type.PRIM}
@@ -132,15 +128,16 @@ export class MapAnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
                             toggleStatus={this.IsTargetToggler()}
                             onClick={this.MakeTargetToggle}
                             icon={<FontAwesomeIcon icon="thumbtack" />}
-                            color={StrCast(Doc.UserDoc().userColor)}
+                            color={SettingsManager.userColor}
                         />
                     )} */}
-                </>
-            );
+            </>
+        );
 
-        return this.getElement(<div ref={MapAnchorMenu.top} style={{width:"100%", display:"flex"}}>
-        {buttons}
-        </div>
+        return this.getElement(
+            <div ref={MapAnchorMenu.top} style={{ width: '100%', display: 'flex' }}>
+                {buttons}
+            </div>
         );
     }
 }
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index 01810fa00..81ca3ff36 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -760,8 +760,9 @@ export class MapBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
                             ? null
                             : this.allAnnotations
                                   .filter(anno => !anno.layout_unrendered)
-                                  .map(pushpin => (
+                                  .map((pushpin, i) => (
                                       <DocumentView
+                                          key={i}
                                           {...this.props}
                                           renderDepth={this.props.renderDepth + 1}
                                           Document={pushpin}
-- 
cgit v1.2.3-70-g09d2


From 74e72adabd59fc58107fd73590f1e7e9cbaf4bde Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 11 Sep 2023 23:19:59 -0400
Subject: clean up some runtime warnings about missing keys/values

---
 package-lock.json                         | 6 +++---
 package.json                              | 2 +-
 src/client/views/MainViewModal.tsx        | 3 ++-
 src/client/views/collections/TreeView.tsx | 6 +++---
 src/client/views/nodes/KeyValuePair.tsx   | 2 +-
 src/client/views/search/SearchBox.tsx     | 4 ++--
 6 files changed, 12 insertions(+), 11 deletions(-)

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

diff --git a/package-lock.json b/package-lock.json
index d15959b7d..e0e54769a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6687,9 +6687,9 @@
             }
         },
         "browndash-components": {
-            "version": "0.1.35",
-            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.35.tgz",
-            "integrity": "sha512-xA4ACEppnDe5ThnUZPn9vo4W/KeZJZT5EFWh2tM0IsH/ZfcOhJopGfV6ZoIHHpvS5f/zi6l7YJuWaxd+aK5arg==",
+            "version": "0.1.36",
+            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.36.tgz",
+            "integrity": "sha512-++Xxn67r9ETz7pQr9dE09dMgPJ6rltEzwYWifpI98AQct4RmEBfiPp5eLG94+143XllxZy++KBf9YJ8AYpTEkQ==",
             "requires": {
                 "@emotion/react": "^11.11.1",
                 "@emotion/styled": "^11.11.0",
diff --git a/package.json b/package.json
index 92ebf0b0f..67fdedeb2 100644
--- a/package.json
+++ b/package.json
@@ -178,7 +178,7 @@
         "body-parser": "^1.19.2",
         "bootstrap": "^4.6.1",
         "brotli": "^1.3.3",
-        "browndash-components": "^0.1.35",
+        "browndash-components": "^0.1.36",
         "browser-assert": "^1.2.1",
         "bson": "^4.6.1",
         "canvas": "^2.9.3",
diff --git a/src/client/views/MainViewModal.tsx b/src/client/views/MainViewModal.tsx
index d0a79eb70..67b722e7a 100644
--- a/src/client/views/MainViewModal.tsx
+++ b/src/client/views/MainViewModal.tsx
@@ -3,6 +3,7 @@ import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc } from '../../fields/Doc';
 import { StrCast } from '../../fields/Types';
+import { SettingsManager } from '../util/SettingsManager';
 import './MainViewModal.scss';
 
 export interface MainViewOverlayProps {
@@ -44,7 +45,7 @@ export class MainViewModal extends React.Component<MainViewOverlayProps> {
                     className="overlay"
                     onClick={this.props?.closeOnExternalClick}
                     style={{
-                        backgroundColor: isDark(StrCast(Doc.UserDoc().userColor)) ? '#DFDFDF30' : '#32323230',
+                        backgroundColor: isDark(SettingsManager.userColor) ? '#DFDFDF30' : '#32323230',
                         ...(p.overlayStyle || {}),
                     }}
                 />
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 71e9f4dfa..832e102bc 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -1015,8 +1015,8 @@ export class TreeView extends React.Component<TreeViewProps> {
                     ref={this._tref}
                     title="click to edit title. Double Click or Drag to Open"
                     style={{
-                        backgroundColor: Doc.IsSystem(this.props.document) || this.props.document.isFolder ? StrCast(Doc.UserDoc().userVariantColor) : undefined,
-                        color: Doc.IsSystem(this.props.document) || this.props.document.isFolder ? lightOrDark(StrCast(Doc.UserDoc().userVariantColor)) : undefined,
+                        backgroundColor: Doc.IsSystem(this.props.document) || this.props.document.isFolder ? SettingsManager.userVariantColor : undefined,
+                        color: Doc.IsSystem(this.props.document) || this.props.document.isFolder ? lightOrDark(SettingsManager.userVariantColor) : undefined,
                         fontWeight: Doc.IsSearchMatch(this.doc) !== undefined ? 'bold' : undefined,
                         textDecoration: Doc.GetT(this.doc, 'title', 'string', true) ? 'underline' : undefined,
                         outline: this.doc === Doc.ActiveDashboard ? 'dashed 1px #06123232' : undefined,
@@ -1045,7 +1045,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                     <div
                         className="treeView-background"
                         style={{
-                            background: StrCast(Doc.UserDoc().userColor),
+                            background: SettingsManager.userColor,
                         }}
                     />
                     {contents}
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index b0d041bdd..f22cb195f 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -111,7 +111,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
                             X
                         </button>
                         <input className="keyValuePair-td-key-check" type="checkbox" style={hover} onChange={this.handleCheck} ref={this.checkbox} />
-                        <Tooltip title={Object.entries(new DocumentOptions()).find((pair: [string, FInfo]) => pair[0].replace(/^_/, '') === props.fieldKey)?.[1].description}>
+                        <Tooltip title={Object.entries(new DocumentOptions()).find((pair: [string, FInfo]) => pair[0].replace(/^_/, '') === props.fieldKey)?.[1].description ?? ''}>
                             <div className="keyValuePair-keyField" style={{ marginLeft: 20 * (props.fieldKey.match(/_/g)?.length || 0), color: keyStyle }}>
                                 {'('.repeat(parenCount)}
                                 {props.fieldKey}
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 6b6b0f2ff..aa46e57dc 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -453,7 +453,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
                 </div>
                 {resultsJSX.length > 0 && (
                     <div className="searchBox-results-container">
-                        <div className="section-header" style={{ background: StrCast(Doc.UserDoc().userVariantColor, Colors.MEDIUM_BLUE) }}>
+                        <div className="section-header" style={{ background: SettingsManager.userVariantColor }}>
                             <div className="section-title">Results</div>
                             <div className="section-subtitle">{`${validResults}` + ' result' + (validResults === 1 ? '' : 's')}</div>
                         </div>
@@ -462,7 +462,7 @@ export class SearchBox extends ViewBoxBaseComponent<SearchBoxProps>() {
                 )}
                 {recommendationsJSX.length > 0 && (
                     <div className="searchBox-recommendations-container">
-                        <div className="section-header" style={{ background: StrCast(Doc.UserDoc().userVariantColor, Colors.MEDIUM_BLUE) }}>
+                        <div className="section-header" style={{ background: SettingsManager.userVariantColor }}>
                             <div className="section-title">Recommendations</div>
                             <div className="section-subtitle">{`${validResults}` + ' result' + (validResults === 1 ? '' : 's')}</div>
                         </div>
-- 
cgit v1.2.3-70-g09d2


From c9ce658d193d5e8ec4161c31bc60c499ada1b8b7 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 19 Sep 2023 16:28:40 -0400
Subject: fixed tree view hierarchy opening icons

---
 src/client/views/collections/TreeView.scss           | 4 +++-
 src/client/views/collections/TreeView.tsx            | 2 +-
 src/client/views/nodes/formattedText/DashDocView.tsx | 1 -
 3 files changed, 4 insertions(+), 3 deletions(-)

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

diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss
index 0cc11bf1c..cbcc7c710 100644
--- a/src/client/views/collections/TreeView.scss
+++ b/src/client/views/collections/TreeView.scss
@@ -21,7 +21,7 @@
     }
 
     .treeView-bulletIcons {
-        width: 100%;
+        margin: auto;
         height: 100%;
         // changes start here.
 
@@ -64,6 +64,8 @@
         position: relative;
         width: fit-content;
         min-height: 20px;
+        min-width: 15px;
+        margin-right: 3px;
         color: $medium-gray;
         border: #80808030 1px solid;
         border-radius: 5px;
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 832e102bc..cd526c77e 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -761,7 +761,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                         <IconButton color={color} icon={<FontAwesomeIcon icon={[this.childDocs?.length && !this.treeViewOpen ? 'fas' : 'far', 'circle']} />} size={Size.XSMALL} />
                     )
                 ) : (
-                    <div className="treeView-bulletIcons" style={{ color: Doc.IsSystem(DocCast(this.doc.proto)) ? 'red' : undefined }}>
+                    <div className="treeView-bulletIcons">
                         <div className={`treeView-${this.onCheckedClick ? 'checkIcon' : 'expandIcon'}`}>
                             <FontAwesomeIcon
                                 size="sm"
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 5349e6966..c5167461b 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -8,7 +8,6 @@ import { NumCast, StrCast } from '../../../../fields/Types';
 import { emptyFunction, returnFalse, Utils } from '../../../../Utils';
 import { DocServer } from '../../../DocServer';
 import { Docs, DocUtils } from '../../../documents/Documents';
-import { ColorScheme } from '../../../util/SettingsManager';
 import { Transform } from '../../../util/Transform';
 import { DocFocusOptions, DocumentView } from '../DocumentView';
 import { FormattedTextBox } from './FormattedTextBox';
-- 
cgit v1.2.3-70-g09d2


From 34f3bab0f4d55b2f55f38e451bfd024994ecff42 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 20 Sep 2023 13:20:53 -0400
Subject: added carousel3D to novice and fixed it's button positions and its
 focus so that it works with trails. added dragging documents within single
 collection for rearranging order of docs in a tab collection.  fixed freeform
 views set to fitWidth to show decorations properly. turned off scaling of
 tree views.  updated lightbox buttons.  fixed tooltips on properties toggles.

---
 src/client/util/CurrentUserUtils.ts                |   4 +-
 src/client/util/DragManager.ts                     |   2 +-
 src/client/views/LightboxView.scss                 |  11 +--
 src/client/views/LightboxView.tsx                  | 106 +++++++++++++--------
 src/client/views/PropertiesButtons.tsx             |  12 ++-
 .../views/collections/CollectionCarousel3DView.tsx |  17 +++-
 src/client/views/collections/CollectionSubView.tsx |   5 +-
 .../views/collections/CollectionTreeView.tsx       |   4 +-
 src/client/views/collections/TreeView.tsx          |   6 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   9 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |   2 +-
 11 files changed, 109 insertions(+), 69 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 259c028cc..2ea5972ee 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -492,8 +492,8 @@ export class CurrentUserUtils {
         const childContextMenuIcons = ["tv", "camera", "users", "times", "trash"]; // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters
         const reqdOpts:DocumentOptions = {
             title: "My Dashboards", childHideLinkButton: true, treeView_FreezeChildren: "remove|add", treeView_HideTitle: true, layout_boxShadow: "0 0", childDontRegisterViews: true,
-            dropAction: "same", treeView_Type: TreeViewType.fileSystem, isFolder: true, isSystem: true,  treeView_TruncateTitleWidth: 350, ignoreClick: true, 
-            layout_headerButton: newDashboardButton, childDragAction: "none",
+            dropAction: "inSame", treeView_Type: TreeViewType.fileSystem, isFolder: true, isSystem: true,  treeView_TruncateTitleWidth: 350, ignoreClick: true, 
+            layout_headerButton: newDashboardButton, childDragAction: "inSame",
             _layout_showTitle: "title", _height: 400, _gridGap: 5, _forceActive: true, _lockedPosition: true,
             contextMenuLabels:new List<string>(contextMenuLabels),
             contextMenuIcons:new List<string>(contextMenuIcons),
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index ed22e70bd..f86f9a3e5 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -14,7 +14,7 @@ import { SelectionManager } from './SelectionManager';
 import { SnappingManager } from './SnappingManager';
 import { UndoManager } from './UndoManager';
 
-export type dropActionType = 'embed' | 'copy' | 'move' | 'add' | 'same' | 'proto' | 'none' | undefined; // undefined = move, "same" = move but don't call dropPropertiesToRemove
+export type dropActionType = 'embed' | 'copy' | 'move' | 'add' | 'same' | 'inSame' | 'proto' | 'none' | undefined; // undefined = move, "same" = move but don't call dropPropertiesToRemove
 
 /**
  * Initialize drag
diff --git a/src/client/views/LightboxView.scss b/src/client/views/LightboxView.scss
index f86a1d211..9a9b8a437 100644
--- a/src/client/views/LightboxView.scss
+++ b/src/client/views/LightboxView.scss
@@ -5,7 +5,6 @@
     top: 10;
     background: transparent;
     border-radius: 8;
-    color: white;
     opacity: 0.7;
     width: 25;
     flex-direction: column;
@@ -17,11 +16,10 @@
 .lightboxView-tabBtn {
     margin: auto;
     position: absolute;
-    right: 38;
+    right: 45;
     top: 10;
     background: transparent;
     border-radius: 8;
-    color: white;
     opacity: 0.7;
     width: 25;
     flex-direction: column;
@@ -33,11 +31,10 @@
 .lightboxView-penBtn {
     margin: auto;
     position: absolute;
-    right: 70;
+    right: 80;
     top: 10;
     background: transparent;
     border-radius: 8;
-    color: white;
     opacity: 0.7;
     width: 25;
     flex-direction: column;
@@ -49,11 +46,10 @@
 .lightboxView-exploreBtn {
     margin: auto;
     position: absolute;
-    right: 100;
+    right: 115;
     top: 10;
     background: transparent;
     border-radius: 8;
-    color: white;
     opacity: 0.7;
     width: 25;
     flex-direction: column;
@@ -68,7 +64,6 @@
     left: 0;
     width: 100%;
     height: 100%;
-    background: #000000bb;
     z-index: 1000;
     .lightboxView-contents {
         position: absolute;
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index 8f081b321..93eaec959 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -1,15 +1,17 @@
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Toggle, ToggleType, Type } from 'browndash-components';
 import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, DocListCast, Opt } from '../../fields/Doc';
 import { InkTool } from '../../fields/InkField';
-import { Cast, NumCast, StrCast } from '../../fields/Types';
+import { BoolCast, Cast, NumCast, StrCast } from '../../fields/Types';
 import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue } from '../../Utils';
 import { DocUtils } from '../documents/Documents';
 import { DocumentManager } from '../util/DocumentManager';
 import { LinkManager } from '../util/LinkManager';
 import { SelectionManager } from '../util/SelectionManager';
+import { SettingsManager } from '../util/SettingsManager';
 import { Transform } from '../util/Transform';
 import { CollectionDockingView } from './collections/CollectionDockingView';
 import { CollectionStackedTimeline } from './collections/CollectionStackedTimeline';
@@ -118,7 +120,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                     width: bottom !== undefined ? undefined : Math.min(this.props.PanelWidth / 4, this.props.maxBorder[0]),
                     bottom,
                 }}>
-                <div className="lightboxView-navBtn" title={color} style={{ top, color: color ? 'red' : 'white', background: color ? 'white' : undefined }} onClick={click}>
+                <div className="lightboxView-navBtn" title={color} style={{ top, color: SettingsManager.userColor, background: undefined }} onClick={click}>
                     <div style={{ height: 10 }}>{color}</div>
                     <FontAwesomeIcon icon={icon as any} size="3x" />
                 </div>
@@ -229,6 +231,7 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                     downx = e.clientX;
                     downy = e.clientY;
                 }}
+                style={{ background: SettingsManager.userBackgroundColor }}
                 onClick={e => {
                     if (Math.abs(downx - e.clientX) < 4 && Math.abs(downy - e.clientY) < 4) {
                         LightboxView.SetLightboxDoc(undefined);
@@ -242,6 +245,8 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                         width: this.lightboxWidth(),
                         height: this.lightboxHeight(),
                         clipPath: `path('${Doc.UserDoc().renderStyle === 'comic' ? wavyBorderPath(this.lightboxWidth(), this.lightboxHeight()) : undefined}')`,
+                        background: SettingsManager.userBackgroundColor,
+                        color: SettingsManager.userColor,
                     }}>
                     {/* <CollectionMenu /> TODO:glr This is where it would go*/}
 
@@ -299,47 +304,68 @@ export class LightboxView extends React.Component<LightboxViewProps> {
                     this.future()?.length.toString()
                 )}
                 <LightboxTourBtn navBtn={this.navBtn} future={this.future} stepInto={this.stepInto} />
-                <div
-                    className="lightboxView-navBtn"
-                    title="toggle fit width"
-                    onClick={e => {
-                        e.stopPropagation();
-                        LightboxView.LightboxDoc!._layout_fitWidth = !LightboxView.LightboxDoc!._layout_fitWidth;
-                    }}>
-                    <FontAwesomeIcon icon={LightboxView.LightboxDoc?._layout_fitWidth ? 'arrows-alt-h' : 'arrows-alt-v'} size="2x" />
+                <div className="lightboxView-navBtn">
+                    <Toggle
+                        tooltip="toggle reading view"
+                        color={SettingsManager.userColor}
+                        background={BoolCast(LightboxView.LightboxDoc!._layout_fitWidth) ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor}
+                        toggleType={ToggleType.BUTTON}
+                        type={Type.TERT}
+                        toggleStatus={BoolCast(LightboxView.LightboxDoc!._layout_fitWidth)}
+                        onClick={e => {
+                            e.stopPropagation();
+                            LightboxView.LightboxDoc!._layout_fitWidth = !LightboxView.LightboxDoc!._layout_fitWidth;
+                        }}
+                        icon={<FontAwesomeIcon icon={LightboxView.LightboxDoc?._layout_fitWidth ? 'book-open' : 'book'} size="sm" />}
+                    />
                 </div>
-                <div
-                    className="lightboxView-tabBtn"
-                    title="open in tab"
-                    onClick={e => {
-                        const lightdoc = LightboxView._docTarget || LightboxView._doc!;
-                        e.stopPropagation();
-                        Doc.RemoveDocFromList(Doc.MyRecentlyClosed, 'data', lightdoc);
-                        CollectionDockingView.AddSplit(lightdoc, OpenWhereMod.none);
-                        SelectionManager.DeselectAll();
-                        LightboxView.SetLightboxDoc(undefined);
-                    }}>
-                    <FontAwesomeIcon icon={'file-download'} size="2x" />
+                <div className="lightboxView-tabBtn">
+                    <Toggle
+                        tooltip="open document in a tab"
+                        color={SettingsManager.userColor}
+                        background={SettingsManager.userBackgroundColor}
+                        toggleType={ToggleType.BUTTON}
+                        type={Type.TERT}
+                        icon={<FontAwesomeIcon icon="file-download" size="sm" />}
+                        onClick={e => {
+                            const lightdoc = LightboxView._docTarget || LightboxView._doc!;
+                            e.stopPropagation();
+                            Doc.RemoveDocFromList(Doc.MyRecentlyClosed, 'data', lightdoc);
+                            CollectionDockingView.AddSplit(lightdoc, OpenWhereMod.none);
+                            SelectionManager.DeselectAll();
+                            LightboxView.SetLightboxDoc(undefined);
+                        }}
+                    />
                 </div>
-                <div
-                    className="lightboxView-penBtn"
-                    title="toggle pen annotation"
-                    style={{ background: Doc.ActiveTool === InkTool.Pen ? 'white' : undefined }}
-                    onClick={e => {
-                        e.stopPropagation();
-                        Doc.ActiveTool = Doc.ActiveTool === InkTool.Pen ? InkTool.None : InkTool.Pen;
-                    }}>
-                    <FontAwesomeIcon color={Doc.ActiveTool === InkTool.Pen ? 'black' : 'white'} icon={'pen'} size="2x" />
+                <div className="lightboxView-penBtn">
+                    <Toggle
+                        tooltip="toggle pen annotation"
+                        color={SettingsManager.userColor}
+                        background={Doc.ActiveTool === InkTool.Pen ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor}
+                        toggleType={ToggleType.BUTTON}
+                        toggleStatus={Doc.ActiveTool === InkTool.Pen}
+                        type={Type.TERT}
+                        icon={<FontAwesomeIcon icon="pen" size="sm" />}
+                        onClick={e => {
+                            e.stopPropagation();
+                            Doc.ActiveTool = Doc.ActiveTool === InkTool.Pen ? InkTool.None : InkTool.Pen;
+                        }}
+                    />
                 </div>
-                <div
-                    className="lightboxView-exploreBtn"
-                    title="toggle explore mode to navigate among documents only"
-                    style={{ background: DocumentView.ExploreMode ? 'white' : undefined }}
-                    onClick={action(e => {
-                        e.stopPropagation();
-                        DocumentView.ExploreMode = !DocumentView.ExploreMode;
-                    })}>
-                    <FontAwesomeIcon color={DocumentView.ExploreMode ? 'black' : 'white'} icon={'globe-americas'} size="2x" />
+                <div className="lightboxView-exploreBtn">
+                    <Toggle
+                        tooltip="toggle explore mode to navigate among documents only"
+                        color={SettingsManager.userColor}
+                        background={DocumentView.ExploreMode ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor}
+                        toggleType={ToggleType.BUTTON}
+                        type={Type.TERT}
+                        toggleStatus={DocumentView.ExploreMode}
+                        icon={<FontAwesomeIcon icon="globe-americas" size="sm" />}
+                        onClick={action(e => {
+                            e.stopPropagation();
+                            DocumentView.ExploreMode = !DocumentView.ExploreMode;
+                        })}
+                    />
                 </div>
             </div>
         );
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 40d42a4de..d1561fd67 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -57,6 +57,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
         return !targetDoc ? null : (
             <Toggle
                 toggleStatus={BoolCast(targetDoc[property])}
+                tooltip={tooltip(BoolCast(targetDoc[property]))}
                 text={label(targetDoc?.[property])}
                 color={SettingsManager.userColor}
                 icon={icon(targetDoc?.[property] as any)}
@@ -165,9 +166,9 @@ export class PropertiesButtons extends React.Component<{}, {}> {
     @computed get forceActiveButton() {
         //select text
         return this.propertyToggleBtn(
-            on => (on ? 'INACTIVE INTERACTION' : 'ACTIVE INTERACTION'),
+            on => (on ? 'SELECT TO INTERACT' : 'ALWAYS INTERACTIVE'),
             '_forceActive',
-            on => `${on ? 'Select to activate' : 'Contents always active'} `,
+            on => `${on ? 'Document must be selected to interact with its contents' : 'Contents always active (respond to click/drag events)'} `,
             on => <MdTouchApp /> // 'eye'
         );
     }
@@ -210,9 +211,12 @@ export class PropertiesButtons extends React.Component<{}, {}> {
 
     @computed get layout_fitWidthButton() {
         return this.propertyToggleBtn(
-            on => (on ? 'RESTRICT WIDTH' : 'FIT WIDTH'), //'Fit\xA0Width',
+            on => (on ? 'SCALED VIEW' : 'READING VIEW'), //'Fit\xA0Width',
             '_layout_fitWidth',
-            on => `${on ? "Don't" : 'Do'} fit content to width of container`,
+            on =>
+                on
+                    ? "Scale document so it's width and height fit container (no effect when document is viewed on freeform canvas)"
+                    : "Scale document so it's width fits container and its height expands/contracts to fit available space  (no effect when document is viewed on freeform canvas)",
             on => (on ? <AiOutlineColumnWidth /> : <RxWidth />) // 'arrows-alt-h'
         );
     }
diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx
index d94e552b4..cd59a91a1 100644
--- a/src/client/views/collections/CollectionCarousel3DView.tsx
+++ b/src/client/views/collections/CollectionCarousel3DView.tsx
@@ -2,14 +2,15 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { computed } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { Doc } from '../../../fields/Doc';
+import { Doc, DocListCast } from '../../../fields/Doc';
 import { Id } from '../../../fields/FieldSymbols';
-import { NumCast, ScriptCast, StrCast } from '../../../fields/Types';
+import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { returnFalse, returnZero, Utils } from '../../../Utils';
+import { DocumentType } from '../../documents/DocumentTypes';
 import { DragManager } from '../../util/DragManager';
 import { SelectionManager } from '../../util/SelectionManager';
 import { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } from '../global/globalCssVariables.scss';
-import { DocumentView } from '../nodes/DocumentView';
+import { DocFocusOptions, DocumentView } from '../nodes/DocumentView';
 import { StyleProp } from '../StyleProvider';
 import './CollectionCarousel3DView.scss';
 import { CollectionSubView } from './CollectionSubView';
@@ -46,6 +47,15 @@ export class CollectionCarousel3DView extends CollectionSubView() {
             .translate(-this.panelWidth() + ((this.centerScale - 1) * this.panelWidth()) / 2, -((Number(CAROUSEL3D_TOP) / 100) * this.props.PanelHeight()) + ((this.centerScale - 1) * this.panelHeight()) / 2)
             .scale(1 / this.centerScale);
 
+    focus = (anchor: Doc, options: DocFocusOptions) => {
+        const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]);
+        if (anchor.type !== DocumentType.CONFIG && !docs.includes(anchor)) return;
+        options.didMove = true;
+        const target = DocCast(anchor.annotationOn) ?? anchor;
+        const index = docs.indexOf(target);
+        index !== -1 && (this.layoutDoc._carousel_index = index);
+        return undefined;
+    };
     @computed get content() {
         const currentIndex = NumCast(this.layoutDoc._carousel_index);
         const displayDoc = (childPair: { layout: Doc; data: Doc }) => {
@@ -61,6 +71,7 @@ export class CollectionCarousel3DView extends CollectionSubView() {
                     LayoutTemplateString={this.props.childLayoutString}
                     Document={childPair.layout}
                     DataDoc={childPair.data}
+                    focus={this.focus}
                     ScreenToLocalTransform={this.childScreenToLocal}
                     isContentActive={this.isChildContentActive}
                     isDocumentActive={this.props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this.props.isDocumentActive : this.isContentActive}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 54a60271a..26272d2ee 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -210,11 +210,12 @@ export function CollectionSubView<X>(moreProps?: X) {
                 const targetDocments = DocListCast(this.dataDoc[this.props.fieldKey]);
                 const someMoved = !dropAction && docDragData.draggedDocuments.some(drag => targetDocments.includes(drag));
                 if (someMoved) docDragData.droppedDocuments = docDragData.droppedDocuments.map((drop, i) => (targetDocments.includes(docDragData.draggedDocuments[i]) ? docDragData.draggedDocuments[i] : drop));
-                if ((!dropAction || dropAction === 'same' || dropAction === 'move' || someMoved) && docDragData.moveDocument) {
+                if ((!dropAction || dropAction === 'inSame' || dropAction === 'same' || dropAction === 'move' || someMoved) && docDragData.moveDocument) {
                     const movedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] === d);
                     const addedDocs = docDragData.droppedDocuments.filter((d, i) => docDragData.draggedDocuments[i] !== d);
                     if (movedDocs.length) {
-                        const canAdd = de.embedKey || dropAction || Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.rootDoc);
+                        const canAdd =
+                            (de.embedKey || dropAction || Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.rootDoc)) && (dropAction !== 'inSame' || docDragData.draggedDocuments.every(d => d.embedContainer === this.rootDoc));
                         const moved = docDragData.moveDocument(movedDocs, this.rootDoc, canAdd ? this.addDocument : returnFalse);
                         added = canAdd || moved ? moved : undefined;
                     } else {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index eed04b3ee..9e5ac77d9 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -149,7 +149,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
             if (isAlreadyInTree() !== sameTree) {
                 console.log('WHAAAT');
             }
-            dragData.dropAction = dropAction && !isAlreadyInTree() ? dropAction : sameTree ? 'same' : dragData.dropAction;
+            dragData.dropAction = dropAction && !isAlreadyInTree() ? dropAction : sameTree && dragData.dropAction !== 'inSame' ? 'same' : dragData.dropAction;
             e.stopPropagation();
         }
     };
@@ -438,7 +438,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
     render() {
         TraceMobx();
 
-        const scale = (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._freeform_scale, 1) || 1;
+        const scale = this.props.NativeDimScaling?.() || 1;
         return (
             <div style={{ transform: `scale(${scale})`, transformOrigin: 'top left', width: `${100 / scale}%`, height: `${100 / scale}%` }}>
                 {!(this.doc instanceof Doc) || !this.treeChildren ? null : this.doc.treeView_HasOverlay ? (
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index cd526c77e..f89aa065b 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -433,9 +433,9 @@ export class TreeView extends React.Component<TreeViewProps> {
             return (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && innerAdd(doc), true as boolean);
         };
         const addDoc = inside ? localAdd : parentAddDoc;
-        const move = (!dropAction || dropAction === 'proto' || dropAction === 'move' || dropAction === 'same') && moveDocument;
+        const move = (!dropAction || dropAction === 'proto' || dropAction === 'move' || dropAction === 'same' || dropAction === 'inSame') && moveDocument;
         const canAdd = (!this.props.treeView.outlineMode && !StrCast((inside ? this.props.document : this.props.treeViewParent)?.treeView_FreezeChildren).includes('add')) || forceAdd;
-        if (canAdd) {
+        if (canAdd && (dropAction !== 'inSame' || droppedDocuments.every(d => d.embedContainer === this.props.parentTreeView?.doc))) {
             this.props.parentTreeView instanceof TreeView && (this.props.parentTreeView.dropping = true);
             const res = droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) || (dropAction === 'proto' ? addDoc(d) : false) : addDoc(d)) || added, false);
             this.props.parentTreeView instanceof TreeView && (this.props.parentTreeView.dropping = false);
@@ -598,7 +598,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 }
                 const dataIsComputed = ComputedField.WithoutComputed(() => FieldValue(this.dataDoc[key])) instanceof ComputedField;
                 const added = (!dataIsComputed || (this.dropping && this.moving)) && Doc.AddDocToList(this.dataDoc, key, doc, addBefore, before, false, true);
-                !dataIsComputed && added && Doc.SetContainer(doc, DocCast(this.doc.embedContainer));
+                !dataIsComputed && added && Doc.SetContainer(doc, this.doc);
 
                 return added;
             };
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 8a812c671..9df96fabc 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -33,7 +33,6 @@ import { undoBatch, UndoManager } from '../../../util/UndoManager';
 import { COLLECTION_BORDER_WIDTH } from '../../../views/global/globalCssVariables.scss';
 import { Timeline } from '../../animationtimeline/Timeline';
 import { ContextMenu } from '../../ContextMenu';
-import { DocumentDecorations } from '../../DocumentDecorations';
 import { GestureOverlay } from '../../GestureOverlay';
 import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, InkingStroke, SetActiveInkColor, SetActiveInkWidth } from '../../InkingStroke';
 import { LightboxView } from '../../LightboxView';
@@ -187,7 +186,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         return this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth);
     }
     @computed get cachedGetTransform(): Transform {
-        return this.getContainerTransform().translate(-this.cachedCenteringShiftX, -this.cachedCenteringShiftY).transform(this.cachedGetLocalTransform);
+        return this.getContainerTransform()
+            .scale(this.props.isAnnotationOverlay ? 1 : 1 / this.nativeDim())
+            .translate(-this.cachedCenteringShiftX, -this.cachedCenteringShiftY)
+            .transform(this.cachedGetLocalTransform);
     }
 
     public static gotoKeyframe(timer: NodeJS.Timeout | undefined, docs: Doc[], duration: number) {
@@ -862,7 +864,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 // create a new curve by appending all curves of the current segment together in order to render a single new stroke.
                 if (!e.shiftKey) {
                     this._eraserLock++;
-                    this.segmentInkStroke(intersect.inkView, intersect.t).forEach(segment =>
+                    const segments = this.segmentInkStroke(intersect.inkView, intersect.t);
+                    segments.forEach(segment =>
                         this.forceStrokeGesture(
                             e,
                             GestureUtils.Gestures.Stroke,
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 394108be4..14a3d16ef 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -226,7 +226,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             } else {
                 return <Button text="None Selected" type={Type.TERT} color={SettingsManager.userColor} background={SettingsManager.userVariantColor} fillWidth inactive />;
             }
-            noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
+            noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Carousel3D, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
         } else {
             text = script?.script.run({ this: this.layoutDoc, self: this.rootDoc, value: '', _readOnly_: true }).result;
             // text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
-- 
cgit v1.2.3-70-g09d2

