From 12d8267533d9b646247914e965b3cf7c32019e4b Mon Sep 17 00:00:00 2001
From: geireann <geireann.lindfield@gmail.com>
Date: Thu, 2 Sep 2021 04:45:01 -0400
Subject: Many updates

- Fixed image uploads so it clones rather than makes an alias
- Updated context menu
- Removed tools panel from novice mode in favour of ":" menu
- Added explainers to menus in novice mode
- Re-added the trails button
- Changed UI for text, PDF & websites so that it is more consistent
---
 .../views/collections/CollectionTreeView.tsx       | 95 ++++++++++++++++------
 1 file changed, 72 insertions(+), 23 deletions(-)

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

diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 89d42439e..4d62a1af4 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -8,7 +8,7 @@ import { Document, listSpec } from '../../../fields/Schema';
 import { ScriptField } from '../../../fields/ScriptField';
 import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
 import { TraceMobx } from '../../../fields/util';
-import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../Utils';
+import { returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, emptyFunction } from '../../../Utils';
 import { DocUtils } from '../../documents/Documents';
 import { CurrentUserUtils } from '../../util/CurrentUserUtils';
 import { DocumentManager } from '../../util/DocumentManager';
@@ -26,6 +26,7 @@ import { CollectionSubView } from "./CollectionSubView";
 import "./CollectionTreeView.scss";
 import { TreeView } from "./TreeView";
 import React = require("react");
+import { Transform } from '../../util/Transform';
 const _global = (window /* browser */ || global /* node */) as any;
 
 export type collectionTreeViewProps = {
@@ -221,8 +222,9 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
     }
     childContextMenuItems = () => {
         const customScripts = Cast(this.doc.childContextMenuScripts, listSpec(ScriptField), []);
-        const filterScripts = Cast(this.doc.childContextMenuFilters, listSpec(ScriptField), []);
-        return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: filterScripts[i], label }));
+        const customFilters = Cast(this.doc.childContextMenuFilters, listSpec(ScriptField), []);
+        const icons = StrListCast(this.doc.childContextMenuIcons);
+        return StrListCast(this.doc.childContextMenuLabels).map((label, i) => ({ script: customScripts[i], filter: customFilters[i], icon: icons[i], label }));
     }
     @computed get treeViewElements() {
         TraceMobx();
@@ -265,13 +267,48 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         return hideTitle ? (null) : (this.outlineMode ? this.documentTitle : this.editableTitle)(this.treeChildren);
     }
 
-    @computed get renderClearButton() {
-        return !this.doc.treeViewShowClearButton ? (null) : <div key="toolbar">
-            <button className="toolbar-button round-button" title="Empty" onClick={undoBatch(action(() => Doc.GetProto(this.doc)[this.props.fieldKey] = undefined))}>
-                <FontAwesomeIcon icon={"trash"} size="sm" />
-            </button>
-        </div >;
+    @computed get buttonMenu() {
+        const menuDoc:Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null);
+        // To create a multibutton menu add a CollectionLinearView
+        if (menuDoc){
+            
+            const width: number = NumCast(menuDoc._width, 30);
+            const height: number = NumCast(menuDoc._height, 30);
+            console.log(menuDoc.title, width, height);
+            return (<div className="buttonMenu-docBtn"
+                style = {{width: width, height: height}}>
+                <DocumentView
+                    Document={menuDoc}
+                    DataDoc={menuDoc}
+                    isContentActive={this.props.isContentActive}
+                    isDocumentActive={returnTrue}
+                    addDocument={this.props.addDocument}
+                    moveDocument={this.props.moveDocument}
+                    addDocTab={this.props.addDocTab}
+                    pinToPres={emptyFunction}
+                    rootSelected={this.props.isSelected}
+                    removeDocument={this.props.removeDocument}
+                    ScreenToLocalTransform={Transform.Identity}
+                    PanelWidth={() => 35}
+                    PanelHeight={() => 35}
+                    renderDepth={this.props.renderDepth + 1}
+                    focus={emptyFunction}
+                    styleProvider={this.props.styleProvider}
+                    layerProvider={this.props.layerProvider}
+                    docViewPath={returnEmptyDoclist}
+                    whenChildContentsActiveChanged={emptyFunction}
+                    bringToFront={emptyFunction}
+                    docFilters={this.props.docFilters}
+                    docRangeFilters={this.props.docRangeFilters}
+                    searchFilterDocs={this.props.searchFilterDocs}
+                    ContainingCollectionView={undefined}
+                    ContainingCollectionDoc={undefined} 
+                />
+            </div>);
+        }
     }
+
+    
     @computed get nativeWidth() { return Doc.NativeWidth(this.Document, undefined, true); }
     @computed get nativeHeight() { return Doc.NativeHeight(this.Document, undefined, true); }
 
@@ -295,22 +332,34 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         TraceMobx();
         const background = () => this.props.styleProvider?.(this.doc, this.props, StyleProp.BackgroundColor);
         const pointerEvents = () => !this.props.isContentActive() && !SnappingManager.GetIsDragging() ? "none" : undefined;
+        const buttonMenu = this.rootDoc.buttonMenu;
+        const noviceExplainer = this.rootDoc.explainer;
 
         return !(this.doc instanceof Doc) || !this.treeChildren ? (null) :
-            <div className="collectionTreeView-container"
-                style={this.outlineMode ? { transform: `scale(${this.contentScaling})`, width: `calc(${100 / this.contentScaling}%)` } : {}}
-                onContextMenu={this.onContextMenu}>
-                <div className="collectionTreeView-dropTarget"
-                    style={{ background: background(), paddingLeft: `${this.paddingX()}px`, paddingRight: `${this.paddingX()}px`, paddingBottom: `${this.paddingBot()}px`, paddingTop: `${this.paddingTop()}px`, pointerEvents: pointerEvents() }}
-                    onWheel={e => e.stopPropagation()}
-                    onDrop={this.onTreeDrop}
-                    ref={this.createTreeDropTarget}>
+               <>
                     {this.titleBar}
-                    {this.renderClearButton}
-                    <ul className={`no-indent${this.outlineMode ? "-outline" : ""}`} >
-                        {this.treeViewElements}
-                    </ul>
-                </div >
-            </div>;
+                    <div className="collectionTreeView-container"
+                        style={this.outlineMode ? { transform: `scale(${this.contentScaling})`, width: `calc(${100 / this.contentScaling}%)` } : {}}
+                        onContextMenu={this.onContextMenu}>
+                        {buttonMenu || noviceExplainer ? <div className="documentButtonMenu">
+                            {buttonMenu ? this.buttonMenu : null}
+                            {Doc.UserDoc().noviceMode && noviceExplainer ? 
+                                <div className="documentExplanation">
+                                    {noviceExplainer}
+                                </div>
+                                : null
+                            }
+                        </div> : null}
+                        <div className="collectionTreeView-dropTarget"
+                            style={{ background: background(), paddingLeft: `${this.paddingX()}px`, paddingRight: `${this.paddingX()}px`, paddingBottom: `${this.paddingBot()}px`, paddingTop: `${this.paddingTop()}px`, pointerEvents: pointerEvents() }}
+                            onWheel={e => e.stopPropagation()}
+                            onDrop={this.onTreeDrop}
+                            ref={this.createTreeDropTarget}>
+                            <ul className={`no-indent${this.outlineMode ? "-outline" : ""}`} >
+                                {this.treeViewElements}
+                            </ul>
+                        </div >
+                    </div>
+               </>;
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From e0240412990f102523b86e324bc973cd2ed523a1 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 14 Sep 2021 22:27:17 -0400
Subject: refactored a bunch of names in MainView.  Fixed scrolling in left
 menu flyout treeview panels.

---
 src/client/views/MainView.scss                     |  62 +---------
 src/client/views/MainView.tsx                      | 126 +++++++++++----------
 src/client/views/collections/CollectionMenu.tsx    |  34 +++---
 .../views/collections/CollectionTreeView.tsx       |  68 +++++------
 src/client/views/collections/TreeView.tsx          |   2 +-
 src/client/views/global/globalCssVariables.scss    |   8 +-
 .../views/global/globalCssVariables.scss.d.ts      |   4 +-
 7 files changed, 130 insertions(+), 174 deletions(-)

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

diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index 817e45699..4f871f5ec 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -15,8 +15,8 @@
     margin-top: 10px;
 }
 
-.mainContent-div-flyout,
-.mainContent-div {
+.mainView-dockingContent-flyout,
+.mainView-dockingContent {
     position: relative;
     width: 100%;
     height: 100%;
@@ -99,7 +99,7 @@
     }
 }
 
-.mainView-mainContent {
+.mainView-dashboardArea {
     width: 100%;
     height: 100%;
     position: absolute;
@@ -208,7 +208,7 @@
     }
 }
 
-.mainView-menuPanel {
+.mainView-leftMenuPanel {
     min-width: var(--menuPanelWidth);
     background-color: $dark-gray;
     border-right: $standard-border;
@@ -220,60 +220,6 @@
     ::-webkit-scrollbar {
         width: 0;
     }
-
-    .mainView-menuPanel-button {
-        padding: 7px;
-        padding-left: 7px;
-        width: 100%;
-        background: $dark-gray;
-
-        .mainView-menuPanel-button-wrap {
-            width: 45px;
-            /* padding: 5px; */
-            touch-action: none;
-            background: $dark-gray;
-            transform-origin: top left;
-            /* margin-bottom: 5px; */
-            margin-top: 5px;
-            margin-right: 25px;
-            border-radius: 8px;
-
-            &:hover {
-                background: $black;
-                cursor: pointer;
-            }
-        }
-    }
-
-    .mainView-menuPanel-button-label {
-        color: white;
-        margin-left: px;
-        margin-right: 4px;
-        border-radius: 8px;
-        width: 42px;
-        position: relative;
-        text-align: center;
-        font-size: 8px;
-        margin-top: 1px;
-        letter-spacing: normal;
-        padding: 3px;
-        background-color: inherit;
-    }
-
-    .mainView-menuPanel-button-icon {
-        width: auto;
-        height: 35px;
-        padding: 5px;
-    }
-}
-
-.mainView-searchPanel {
-    width: 100%;
-    height: $searchpanel-height;
-    background-color: black;
-    color: white;
-    text-align: center;
-    vertical-align: middle;
 }
 
 .mainView-mainDiv {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index b102c9a1f..5bda9f6bf 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -11,9 +11,10 @@ import * as ReactDOM from 'react-dom';
 import { Doc, DocListCast, Opt } from '../../fields/Doc';
 import { List } from '../../fields/List';
 import { PrefetchProxy } from '../../fields/Proxy';
+import { ScriptField } from '../../fields/ScriptField';
 import { BoolCast, PromiseValue, StrCast } from '../../fields/Types';
 import { TraceMobx } from '../../fields/util';
-import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from '../../Utils';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick, Utils } from '../../Utils';
 import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
 import { DocServer } from '../DocServer';
 import { Docs, DocUtils } from '../documents/Documents';
@@ -36,11 +37,12 @@ import { CollectionLinearView } from './collections/collectionLinear';
 import { CollectionMenu } from './collections/CollectionMenu';
 import { CollectionViewType } from './collections/CollectionView';
 import "./collections/TreeView.scss";
+import { ComponentDecorations } from './ComponentDecorations';
 import { ContextMenu } from './ContextMenu';
 import { DictationOverlay } from './DictationOverlay';
 import { DocumentDecorations } from './DocumentDecorations';
 import { GestureOverlay } from './GestureOverlay';
-import { MENU_PANEL_WIDTH, SEARCH_PANEL_HEIGHT } from './global/globalCssVariables.scss';
+import { DASHBOARD_SELECTOR_HEIGHT, LEFT_MENU_WIDTH } from './global/globalCssVariables.scss';
 import { Colors } from './global/globalEnums';
 import { KeyManager } from './GlobalKeyHandler';
 import { InkStrokeProperties } from './InkStrokeProperties';
@@ -48,9 +50,11 @@ import { LightboxView } from './LightboxView';
 import { LinkMenu } from './linking/LinkMenu';
 import "./MainView.scss";
 import { AudioBox } from './nodes/AudioBox';
+import { ButtonType } from './nodes/button/FontIconBox';
 import { DocumentLinksButton } from './nodes/DocumentLinksButton';
 import { DocumentView } from './nodes/DocumentView';
 import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
+import { RichTextMenu } from './nodes/formattedText/RichTextMenu';
 import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup';
 import { LinkDocPreview } from './nodes/LinkDocPreview';
 import { RadialMenu } from './nodes/RadialMenu';
@@ -62,10 +66,6 @@ import { PreviewCursor } from './PreviewCursor';
 import { PropertiesView } from './PropertiesView';
 import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider';
 import { TopBar } from './topbar/TopBar';
-import { RichTextMenu } from './nodes/formattedText/RichTextMenu';
-import { ScriptField } from '../../fields/ScriptField';
-import { ButtonType } from './nodes/button/FontIconBox';
-import { ComponentDecorations } from './ComponentDecorations';
 const _global = (window /* browser */ || global /* node */) as any;
 
 @observer
@@ -76,21 +76,32 @@ export class MainView extends React.Component {
     @observable public LastButton: Opt<Doc>;
     @observable private _windowWidth: number = 0;
     @observable private _windowHeight: number = 0;
-    @observable private _panelWidth: number = 0;
-    @observable private _panelHeight: number = 0;
+    @observable private _dashUIWidth: number = 0;   // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row)
+    @observable private _dashUIHeight: number = 0;  // height of entire main dashboard region including top menu buttons
     @observable private _panelContent: string = "none";
     @observable private _sidebarContent: any = this.userDoc?.sidebar;
-    @observable private _flyoutWidth: number = 0;
+    @observable private _leftMenuFlyoutWidth: number = 0;
 
-    @computed private get topOffset() { return 35 + Number(SEARCH_PANEL_HEIGHT.replace("px", "")); } //TODO remove
-    @computed private get leftOffset() { return this.menuPanelWidth() - 2; }
+    @computed private get dashboardTabHeight() { return 27; } //  27 comes form lm.config.defaultConfig.dimensions.headerHeight in goldenlayout.js
+    @computed private get topOfDashUI() { return Number(DASHBOARD_SELECTOR_HEIGHT.replace("px", "")); }
+    @computed private get topOfMainDoc() { return this.topOfDashUI + this.topMenuHeight(); }
+    @computed private get topOfMainDocContent() { return this.topOfMainDoc + this.dashboardTabHeight; }
+    @computed private get leftScreenOffsetOfMainDocView() { return this.leftMenuWidth() - 2; }
     @computed private get userDoc() { return Doc.UserDoc(); }
     @computed private get darkScheme() { return BoolCast(CurrentUserUtils.ActiveDashboard?.darkScheme); }
     @computed private get mainContainer() { return this.userDoc ? CurrentUserUtils.ActiveDashboard : CurrentUserUtils.GuestDashboard; }
-    @computed public get mainFreeform(): Opt<Doc> { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); }
-
-    menuPanelWidth = () => Number(MENU_PANEL_WIDTH.replace("px", ""));
-    propertiesWidth = () => Math.max(0, Math.min(this._panelWidth - 50, CurrentUserUtils.propertiesWidth || 0));
+    @computed public get mainFreeform(): Opt<Doc> { return (docs => (docs?.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); }
+
+    topMenuHeight = () => 35;
+    topMenuWidth = returnZero; // value is ignored ...
+    leftMenuWidth = () => Number(LEFT_MENU_WIDTH.replace("px", ""));
+    leftMenuHeight = () => this._dashUIHeight;
+    leftMenuFlyoutWidth = () => this._leftMenuFlyoutWidth;
+    leftMenuFlyoutHeight = () => this._dashUIHeight;
+    propertiesWidth = () => Math.max(0, Math.min(this._dashUIWidth - 50, CurrentUserUtils.propertiesWidth || 0));
+    propertiesHeight = () => this._dashUIHeight;
+    mainDocViewWidth = () => this._dashUIWidth - this.propertiesWidth() - this.leftMenuWidth();
+    mainDocViewHeight = () => this._dashUIHeight - this.topMenuHeight();
 
     componentDidMount() {
         document.getElementById("root")?.addEventListener("scroll", e => ((ele) => ele.scrollLeft = ele.scrollTop = 0)(document.getElementById("root")!));
@@ -264,11 +275,6 @@ export class MainView extends React.Component {
         Doc.AddDocToList(this.userDoc.myFilesystem as Doc, "data", folder);
     }
 
-    getPWidth = () => this._panelWidth - this.propertiesWidth();
-    getPHeight = () => this._panelHeight - (CollectionMenu.Instance?.Pinned ? 35 : 0);
-    getContentsHeight = () => this._panelHeight;
-    getMenuPanelHeight = () => this._panelHeight + (CollectionMenu.Instance?.Pinned ? 35 : 0);
-
     @computed get mainDocView() {
         return <DocumentView key="main"
             Document={this.mainContainer!}
@@ -283,8 +289,8 @@ export class MainView extends React.Component {
             isContentActive={returnTrue}
             removeDocument={undefined}
             ScreenToLocalTransform={Transform.Identity}
-            PanelWidth={this.getPWidth}
-            PanelHeight={this.getPHeight}
+            PanelWidth={this.mainDocViewWidth}
+            PanelHeight={this.mainDocViewHeight}
             focus={DocUtils.DefaultFocus}
             whenChildContentsActiveChanged={emptyFunction}
             bringToFront={emptyFunction}
@@ -298,11 +304,9 @@ export class MainView extends React.Component {
     }
 
     @computed get dockingContent() {
-        return <div key="docking" className={`mainContent-div${this._flyoutWidth ? "-flyout" : ""}`} onDrop={e => { e.stopPropagation(); e.preventDefault(); }}
-            // style={{ minWidth: `calc(100% - ${this._flyoutWidth + this.menuPanelWidth() + this.propertiesWidth()}px)`, width: `calc(100% - ${this._flyoutWidth + this.propertiesWidth()}px)` }}>
-            // FIXME update with property panel width
+        return <div key="docking" className={`mainView-dockingContent${this._leftMenuFlyoutWidth ? "-flyout" : ""}`} onDrop={e => { e.stopPropagation(); e.preventDefault(); }}
             style={{
-                minWidth: `calc(100% - ${this._flyoutWidth + this.menuPanelWidth() + this.propertiesWidth()}px)`,
+                minWidth: `calc(100% - ${this._leftMenuFlyoutWidth + this.leftMenuWidth() + this.propertiesWidth()}px)`,
                 transform: LightboxView.LightboxDoc ? "scale(0.0001)" : undefined,
             }}>
             {!this.mainContainer ? (null) : this.mainDocView}
@@ -312,22 +316,21 @@ export class MainView extends React.Component {
     @action
     onPropertiesPointerDown = (e: React.PointerEvent) => {
         setupMoveUpEvents(this, e,
-            action(e => (CurrentUserUtils.propertiesWidth = Math.max(0, this._panelWidth - e.clientX)) ? false : false),
+            action(e => (CurrentUserUtils.propertiesWidth = Math.max(0, this._dashUIWidth - e.clientX)) ? false : false),
             action(() => CurrentUserUtils.propertiesWidth < 5 && (CurrentUserUtils.propertiesWidth = 0)),
-            action(() => CurrentUserUtils.propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._panelWidth - 50, 250) : 0), false);
+            action(() => CurrentUserUtils.propertiesWidth = this.propertiesWidth() < 15 ? Math.min(this._dashUIWidth - 50, 250) : 0), false);
     }
 
     @action
     onFlyoutPointerDown = (e: React.PointerEvent) => {
         setupMoveUpEvents(this, e,
-            action(e => (this._flyoutWidth = Math.max(e.clientX - 58, 0)) ? false : false),
-            () => this._flyoutWidth < 5 && this.closeFlyout(),
+            action(e => (this._leftMenuFlyoutWidth = Math.max(e.clientX - 58, 0)) ? false : false),
+            () => this._leftMenuFlyoutWidth < 5 && this.closeFlyout(),
             this.closeFlyout);
     }
 
-    flyoutWidthFunc = () => this._flyoutWidth;
-    sidebarScreenToLocal = () => new Transform(0, -this.topOffset, 1);
-    mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftOffset, 0);
+    sidebarScreenToLocal = () => new Transform(0, -this.topOfMainDoc, 1);
+    mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftScreenOffsetOfMainDocView, 0);
     addDocTabFunc = (doc: Doc, where: string): boolean => {
         return where === "close" ? CollectionDockingView.CloseSplit(doc) :
             doc.dockingConfig ? CurrentUserUtils.openDashboard(Doc.UserDoc(), doc) : CollectionDockingView.AddSplit(doc, "right");
@@ -335,10 +338,10 @@ export class MainView extends React.Component {
 
 
     @computed get flyout() {
-        return !this._flyoutWidth ? <div key="flyout" className={`mainView-libraryFlyout-out`}>
+        return !this._leftMenuFlyoutWidth ? <div key="flyout" className={`mainView-libraryFlyout-out`}>
             {this.docButtons}
         </div> :
-            <div key="libFlyout" className="mainView-libraryFlyout" style={{ minWidth: this._flyoutWidth, width: this._flyoutWidth }} >
+            <div key="libFlyout" className="mainView-libraryFlyout" style={{ minWidth: this._leftMenuFlyoutWidth, width: this._leftMenuFlyoutWidth }} >
                 <div className="mainView-contentArea" >
                     <DocumentView
                         Document={this._sidebarContent.proto || this._sidebarContent}
@@ -352,8 +355,8 @@ export class MainView extends React.Component {
                         rootSelected={returnTrue}
                         removeDocument={returnFalse}
                         ScreenToLocalTransform={this.mainContainerXf}
-                        PanelWidth={this.flyoutWidthFunc}
-                        PanelHeight={this.getContentsHeight}
+                        PanelWidth={this.leftMenuFlyoutWidth}
+                        PanelHeight={this.leftMenuFlyoutHeight}
                         renderDepth={0}
                         isContentActive={returnTrue}
                         scriptContext={CollectionDockingView.Instance?.props.Document}
@@ -371,8 +374,8 @@ export class MainView extends React.Component {
             </div>;
     }
 
-    @computed get menuPanel() {
-        return <div key="menu" className="mainView-menuPanel">
+    @computed get leftMenuPanel() {
+        return <div key="menu" className="mainView-leftMenuPanel">
             <DocumentView
                 Document={Doc.UserDoc().menuStack as Doc}
                 DataDoc={undefined}
@@ -382,8 +385,8 @@ export class MainView extends React.Component {
                 rootSelected={returnTrue}
                 removeDocument={returnFalse}
                 ScreenToLocalTransform={this.sidebarScreenToLocal}
-                PanelWidth={this.menuPanelWidth}
-                PanelHeight={this.getMenuPanelHeight}
+                PanelWidth={this.leftMenuWidth}
+                PanelHeight={this.leftMenuHeight}
                 renderDepth={0}
                 docViewPath={returnEmptyDoclist}
                 focus={DocUtils.DefaultFocus}
@@ -405,7 +408,7 @@ export class MainView extends React.Component {
     @action
     selectMenu = (button: Doc) => {
         const title = StrCast(Doc.GetProto(button).title);
-        const willOpen = !this._flyoutWidth || this._panelContent !== title;
+        const willOpen = !this._leftMenuFlyoutWidth || this._panelContent !== title;
         this.closeFlyout();
         if (willOpen) {
             switch (this._panelContent = title) {
@@ -422,38 +425,41 @@ export class MainView extends React.Component {
     }
 
     @computed get mainInnerContent() {
-        const width = this.propertiesWidth() + this._flyoutWidth + this.menuPanelWidth();
-        const transform = this._flyoutWidth ? 'translate(-28px, 0px)' : undefined;
+        const width = this.propertiesWidth() + this._leftMenuFlyoutWidth + this.leftMenuWidth();
+        const transform = this._leftMenuFlyoutWidth ? 'translate(-28px, 0px)' : undefined;
         return <>
-            {this.menuPanel}
+            {this.leftMenuPanel}
             <div key="inner" className={`mainView-innerContent${this.darkScheme ? "-dark" : ""}`}>
                 {this.flyout}
-                <div className="mainView-libraryHandle" style={{ display: !this._flyoutWidth ? "none" : undefined }} onPointerDown={this.onFlyoutPointerDown} >
+                <div className="mainView-libraryHandle" style={{ display: !this._leftMenuFlyoutWidth ? "none" : undefined }} onPointerDown={this.onFlyoutPointerDown} >
                     <FontAwesomeIcon icon="chevron-left" color={this.darkScheme ? "white" : "black"} style={{ opacity: "50%" }} size="sm" />
                 </div>
                 <div className="mainView-innerContainer" style={{ width: `calc(100% - ${width}px)`, transform: transform }}>
-                    <CollectionMenu />
+                    <CollectionMenu panelWidth={this.topMenuWidth} panelHeight={this.topMenuHeight} />
 
                     {this.dockingContent}
 
-                    <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ right: this._flyoutWidth ? 0 : this.propertiesWidth() - 1 }}>
+                    <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ right: this._leftMenuFlyoutWidth ? 0 : this.propertiesWidth() - 1 }}>
                         <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? "chevron-left" : "chevron-right"} color={this.darkScheme ? Colors.WHITE : Colors.BLACK} size="sm" />
                     </div>
                     <div className="properties-container">
-                        {this.propertiesWidth() < 10 ? (null) : <PropertiesView styleProvider={DefaultStyleProvider} width={this.propertiesWidth()} height={this.getContentsHeight()} />}
+                        {this.propertiesWidth() < 10 ? (null) : <PropertiesView styleProvider={DefaultStyleProvider} width={this.propertiesWidth()} height={this.propertiesHeight()} />}
                     </div>
                 </div>
             </div>
         </>;
     }
 
-    @computed get mainContent() {
+    @computed get mainDashboardArea() {
         return !this.userDoc ? (null) :
-            <div className="mainView-mainContent" ref={r => {
-                r && new _global.ResizeObserver(action(() => { this._panelWidth = r.getBoundingClientRect().width; this._panelHeight = r.getBoundingClientRect().height; })).observe(r);
+            <div className="mainView-dashboardArea" ref={r => {
+                r && new _global.ResizeObserver(action(() => {
+                    this._dashUIWidth = r.getBoundingClientRect().width;
+                    this._dashUIHeight = r.getBoundingClientRect().height;
+                })).observe(r);
             }} style={{
                 color: this.darkScheme ? "rgb(205,205,205)" : "black",
-                height: `calc(100% - ${this.topOffset - 35}px)`,
+                height: `calc(100% - ${this.topOfDashUI}px)`,
                 width: "100%",
             }} >
                 {this.mainInnerContent}
@@ -461,7 +467,7 @@ export class MainView extends React.Component {
     }
 
     expandFlyout = action((button: Doc) => {
-        this._flyoutWidth = (this._flyoutWidth || 250);
+        this._leftMenuFlyoutWidth = (this._leftMenuFlyoutWidth || 250);
         this._sidebarContent.proto = button.target as any;
         this.LastButton = button;
         console.log(button.title);
@@ -471,7 +477,7 @@ export class MainView extends React.Component {
         this.LastButton = undefined;
         this._panelContent = "none";
         this._sidebarContent.proto = undefined;
-        this._flyoutWidth = 0;
+        this._leftMenuFlyoutWidth = 0;
     });
 
     remButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.RemoveDocFromList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true);
@@ -509,8 +515,8 @@ export class MainView extends React.Component {
                     pinToPres={emptyFunction}
                     removeDocument={this.remButtonDoc}
                     ScreenToLocalTransform={this.buttonBarXf}
-                    PanelWidth={this.flyoutWidthFunc}
-                    PanelHeight={this.getContentsHeight}
+                    PanelWidth={this.leftMenuFlyoutWidth}
+                    PanelHeight={this.leftMenuFlyoutHeight}
                     renderDepth={0}
                     focus={DocUtils.DefaultFocus}
                     whenChildContentsActiveChanged={emptyFunction}
@@ -606,14 +612,14 @@ export class MainView extends React.Component {
             <CaptureManager />
             <GroupManager />
             <GoogleAuthenticationManager />
-            <DocumentDecorations PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} boundsLeft={this.leftOffset} boundsTop={this.topOffset} />
-            <ComponentDecorations boundsLeft={this.leftOffset} boundsTop={this.topOffset + 27} /> {/*  27 comes form lm.config.defaultConfig.dimensions.headerHeight in goldenlayout.js */}
+            <DocumentDecorations boundsLeft={this.leftScreenOffsetOfMainDocView} boundsTop={this.topOfMainDoc} PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} />
+            <ComponentDecorations boundsLeft={this.leftScreenOffsetOfMainDocView} boundsTop={this.topOfMainDocContent} />
             {this.topbar}
             {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
             {DocumentLinksButton.LinkEditorDocView ? <LinkMenu docView={DocumentLinksButton.LinkEditorDocView} changeFlyout={emptyFunction} /> : (null)}
             {LinkDocPreview.LinkInfo ? <LinkDocPreview {...LinkDocPreview.LinkInfo} /> : (null)}
             <GestureOverlay >
-                {this.mainContent}
+                {this.mainDashboardArea}
             </GestureOverlay>
             <PreviewCursor />
             <TaskCompletionBox />
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 6ffa6c279..8e03b2db2 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -42,8 +42,13 @@ import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView";
 import { TabDocView } from "./TabDocView";
 import { Colors } from "../global/globalEnums";
 
+interface CollectionMenuProps {
+    panelHeight: () => number;
+    panelWidth: () => number;
+}
+
 @observer
-export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
+export class CollectionMenu extends AntimodeMenu<CollectionMenuProps>{
     @observable static Instance: CollectionMenu;
 
     @observable SelectedCollection: DocumentView | undefined;
@@ -93,13 +98,10 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
         return new Transform(-translateX, -translateY, 1 / scale);
     }
 
-    panelWidth100 = () => 100;
-    panelHeight35 = () => 35;
-
     @computed get contMenuButtons() {
         trace();
         const selDoc = Doc.UserDoc().contextMenuBtns;
-        return !(selDoc instanceof Doc) ? (null) : <div className="collectionMenu-contMenuButtons" ref={this._docBtnRef} style={{ height: "35px" }} >
+        return !(selDoc instanceof Doc) ? (null) : <div className="collectionMenu-contMenuButtons" ref={this._docBtnRef} style={{ height: this.props.panelHeight() }} >
             <CollectionLinearView
                 Document={selDoc}
                 DataDoc={undefined}
@@ -122,8 +124,8 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
                 pinToPres={emptyFunction}
                 removeDocument={returnFalse}
                 ScreenToLocalTransform={this.buttonBarXf}
-                PanelWidth={this.panelWidth100}
-                PanelHeight={this.panelHeight35}
+                PanelWidth={this.props.panelWidth}
+                PanelHeight={this.props.panelHeight}
                 renderDepth={0}
                 focus={emptyFunction}
                 whenChildContentsActiveChanged={emptyFunction}
@@ -176,7 +178,7 @@ export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> {
     }
 }
 
-interface CollectionMenuProps {
+interface CollectionViewMenuProps {
     type: CollectionViewType;
     fieldKey: string;
     docView: DocumentView;
@@ -185,7 +187,7 @@ interface CollectionMenuProps {
 const stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation();
 
 @observer
-export class CollectionViewBaseChrome extends React.Component<CollectionMenuProps> {
+export class CollectionViewBaseChrome extends React.Component<CollectionViewMenuProps> {
     //(!)?\(\(\(doc.(\w+) && \(doc.\w+ as \w+\).includes\(\"(\w+)\"\)
 
     get document() { return this.props.docView?.props.Document; }
@@ -628,14 +630,14 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
 }
 
 @observer
-export class CollectionDockingChrome extends React.Component<CollectionMenuProps> {
+export class CollectionDockingChrome extends React.Component<CollectionViewMenuProps> {
     render() {
         return (null);
     }
 }
 
 @observer
-export class CollectionFreeFormViewChrome extends React.Component<CollectionMenuProps & { isOverlay: boolean, isDoc?: boolean }> {
+export class CollectionFreeFormViewChrome extends React.Component<CollectionViewMenuProps & { isOverlay: boolean, isDoc?: boolean }> {
     public static Instance: CollectionFreeFormViewChrome;
     constructor(props: any) {
         super(props);
@@ -866,7 +868,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     }
 }
 @observer
-export class CollectionStackingViewChrome extends React.Component<CollectionMenuProps> {
+export class CollectionStackingViewChrome extends React.Component<CollectionViewMenuProps> {
     @observable private _currentKey: string = "";
     @observable private suggestions: string[] = [];
 
@@ -987,7 +989,7 @@ export class CollectionStackingViewChrome extends React.Component<CollectionMenu
 
 
 @observer
-export class CollectionSchemaViewChrome extends React.Component<CollectionMenuProps> {
+export class CollectionSchemaViewChrome extends React.Component<CollectionViewMenuProps> {
     // private _textwrapAllRows: boolean = Cast(this.document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
     get document() { return this.props.docView.props.Document; }
 
@@ -1035,7 +1037,7 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionMenuPr
 }
 
 @observer
-export class CollectionTreeViewChrome extends React.Component<CollectionMenuProps> {
+export class CollectionTreeViewChrome extends React.Component<CollectionViewMenuProps> {
 
     get document() { return this.props.docView.props.Document; }
     get sortAscending() {
@@ -1072,7 +1074,7 @@ export class CollectionTreeViewChrome extends React.Component<CollectionMenuProp
 
 // Enter scroll speed for 3D Carousel 
 @observer
-export class Collection3DCarouselViewChrome extends React.Component<CollectionMenuProps> {
+export class Collection3DCarouselViewChrome extends React.Component<CollectionViewMenuProps> {
     get document() { return this.props.docView.props.Document; }
     @computed get scrollSpeed() {
         return this.document._autoScrollSpeed;
@@ -1113,7 +1115,7 @@ export class Collection3DCarouselViewChrome extends React.Component<CollectionMe
  * Chrome for grid view.
  */
 @observer
-export class CollectionGridViewChrome extends React.Component<CollectionMenuProps> {
+export class CollectionGridViewChrome extends React.Component<CollectionViewMenuProps> {
 
     private clicked: boolean = false;
     private entered: boolean = false;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 4d62a1af4..624a0bf4a 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -267,16 +267,17 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         return hideTitle ? (null) : (this.outlineMode ? this.documentTitle : this.editableTitle)(this.treeChildren);
     }
 
+    return35 = () => 35;
     @computed get buttonMenu() {
-        const menuDoc:Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null);
+        const menuDoc: Doc = Cast(this.rootDoc.buttonMenuDoc, Doc, null);
         // To create a multibutton menu add a CollectionLinearView
-        if (menuDoc){
-            
+        if (menuDoc) {
+
             const width: number = NumCast(menuDoc._width, 30);
             const height: number = NumCast(menuDoc._height, 30);
             console.log(menuDoc.title, width, height);
             return (<div className="buttonMenu-docBtn"
-                style = {{width: width, height: height}}>
+                style={{ width: width, height: height }}>
                 <DocumentView
                     Document={menuDoc}
                     DataDoc={menuDoc}
@@ -289,8 +290,8 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
                     rootSelected={this.props.isSelected}
                     removeDocument={this.props.removeDocument}
                     ScreenToLocalTransform={Transform.Identity}
-                    PanelWidth={() => 35}
-                    PanelHeight={() => 35}
+                    PanelWidth={this.return35}
+                    PanelHeight={this.return35}
                     renderDepth={this.props.renderDepth + 1}
                     focus={emptyFunction}
                     styleProvider={this.props.styleProvider}
@@ -302,13 +303,14 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
                     docRangeFilters={this.props.docRangeFilters}
                     searchFilterDocs={this.props.searchFilterDocs}
                     ContainingCollectionView={undefined}
-                    ContainingCollectionDoc={undefined} 
+                    ContainingCollectionDoc={undefined}
                 />
             </div>);
         }
     }
 
-    
+    @observable _explainerHeight: number = 0;
+
     @computed get nativeWidth() { return Doc.NativeWidth(this.Document, undefined, true); }
     @computed get nativeHeight() { return Doc.NativeHeight(this.Document, undefined, true); }
 
@@ -336,30 +338,30 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         const noviceExplainer = this.rootDoc.explainer;
 
         return !(this.doc instanceof Doc) || !this.treeChildren ? (null) :
-               <>
-                    {this.titleBar}
-                    <div className="collectionTreeView-container"
-                        style={this.outlineMode ? { transform: `scale(${this.contentScaling})`, width: `calc(${100 / this.contentScaling}%)` } : {}}
-                        onContextMenu={this.onContextMenu}>
-                        {buttonMenu || noviceExplainer ? <div className="documentButtonMenu">
-                            {buttonMenu ? this.buttonMenu : null}
-                            {Doc.UserDoc().noviceMode && noviceExplainer ? 
-                                <div className="documentExplanation">
-                                    {noviceExplainer}
-                                </div>
-                                : null
-                            }
-                        </div> : null}
-                        <div className="collectionTreeView-dropTarget"
-                            style={{ background: background(), paddingLeft: `${this.paddingX()}px`, paddingRight: `${this.paddingX()}px`, paddingBottom: `${this.paddingBot()}px`, paddingTop: `${this.paddingTop()}px`, pointerEvents: pointerEvents() }}
-                            onWheel={e => e.stopPropagation()}
-                            onDrop={this.onTreeDrop}
-                            ref={this.createTreeDropTarget}>
-                            <ul className={`no-indent${this.outlineMode ? "-outline" : ""}`} >
-                                {this.treeViewElements}
-                            </ul>
-                        </div >
-                    </div>
-               </>;
+            <>
+                {this.titleBar}
+                <div className="collectionTreeView-container"
+                    style={this.outlineMode ? { transform: `scale(${this.contentScaling})`, width: `calc(${100 / this.contentScaling}%)` } : {}}
+                    onContextMenu={this.onContextMenu}>
+                    {buttonMenu || noviceExplainer ? <div className="documentButtonMenu" ref={action((r: HTMLDivElement) => r && (this._explainerHeight = r.getBoundingClientRect().height))}>
+                        {buttonMenu ? this.buttonMenu : null}
+                        {Doc.UserDoc().noviceMode && noviceExplainer ?
+                            <div className="documentExplanation">
+                                {noviceExplainer}
+                            </div>
+                            : null
+                        }
+                    </div> : null}
+                    <div className="collectionTreeView-dropTarget"
+                        style={{ background: background(), height: `calc(100% - ${this._explainerHeight}px)`, paddingLeft: `${this.paddingX()}px`, paddingRight: `${this.paddingX()}px`, paddingBottom: `${this.paddingBot()}px`, paddingTop: `${this.paddingTop()}px`, pointerEvents: pointerEvents() }}
+                        onWheel={e => e.stopPropagation()}
+                        onDrop={this.onTreeDrop}
+                        ref={this.createTreeDropTarget}>
+                        <ul className={`no-indent${this.outlineMode ? "-outline" : ""}`} >
+                            {this.treeViewElements}
+                        </ul>
+                    </div >
+                </div>
+            </>;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index aa7b164b0..4fc25752f 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -869,7 +869,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             const childLayout = Doc.Layout(pair.layout);
             const rowHeight = () => {
                 const aspect = Doc.NativeAspect(childLayout);
-                return aspect ? Math.min(childLayout[WidthSym](), rowWidth()) / aspect : childLayout[HeightSym]();
+                return (aspect ? Math.min(childLayout[WidthSym](), rowWidth()) / aspect : childLayout[HeightSym]());
             };
             return <TreeView key={child[Id]} ref={r => treeViewRefs.set(child, r ? r : undefined)}
                 document={pair.layout}
diff --git a/src/client/views/global/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss
index caa9f4fe5..95bd44c1f 100644
--- a/src/client/views/global/globalCssVariables.scss
+++ b/src/client/views/global/globalCssVariables.scss
@@ -54,7 +54,7 @@ $standard-border-radius: 3px;
 $standard-box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
 
 
-$searchpanel-height: 32px;
+$dashboardselector-height: 32px;
 $mainTextInput-zindex: 999; // then text input overlay so that it's context menu will appear over decorations, etc
 $docDecorations-zindex: 998; // then doc decorations appear over everything else
 $remoteCursors-zindex: 997; // ... not sure what level the remote cursors should go -- is this right?
@@ -63,7 +63,7 @@ $SCHEMA_DIVIDER_WIDTH: 4;
 $MINIMIZED_ICON_SIZE: 24;
 $MAX_ROW_HEIGHT: 44px;
 $DFLT_IMAGE_NATIVE_DIM: 900px;
-$MENU_PANEL_WIDTH: 60px;
+$LEFT_MENU_WIDTH: 60px;
 $TREE_BULLET_WIDTH: 20px;
 
 :export {
@@ -74,8 +74,8 @@ $TREE_BULLET_WIDTH: 20px;
     MAX_ROW_HEIGHT: $MAX_ROW_HEIGHT;
     SEARCH_THUMBNAIL_SIZE: $search-thumnail-size;
     ANTIMODEMENU_HEIGHT: $antimodemenu-height;
-    SEARCH_PANEL_HEIGHT: $searchpanel-height;
+    DASHBOARD_SELECTOR_HEIGHT: $dashboardselector-height;
     DFLT_IMAGE_NATIVE_DIM: $DFLT_IMAGE_NATIVE_DIM;
-    MENU_PANEL_WIDTH: $MENU_PANEL_WIDTH;
+    LEFT_MENU_WIDTH: $LEFT_MENU_WIDTH;
     TREE_BULLET_WIDTH: $TREE_BULLET_WIDTH;
 }
\ No newline at end of file
diff --git a/src/client/views/global/globalCssVariables.scss.d.ts b/src/client/views/global/globalCssVariables.scss.d.ts
index 11e62e1eb..59c2b3585 100644
--- a/src/client/views/global/globalCssVariables.scss.d.ts
+++ b/src/client/views/global/globalCssVariables.scss.d.ts
@@ -7,9 +7,9 @@ interface IGlobalScss {
     MAX_ROW_HEIGHT: string;
     SEARCH_THUMBNAIL_SIZE: string;
     ANTIMODEMENU_HEIGHT: string;
-    SEARCH_PANEL_HEIGHT: string;
+    DASHBOARD_SELECTOR_HEIGHT: string;
     DFLT_IMAGE_NATIVE_DIM: string;
-    MENU_PANEL_WIDTH: string;
+    LEFT_MENU_WIDTH: string;
     TREE_BULLET_WIDTH: string;
 }
 declare const globalCssVariables: IGlobalScss;
-- 
cgit v1.2.3-70-g09d2


From 1ca0db9a94e8f1141f8f52446afb53e29cff0e01 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 15 Sep 2021 09:30:15 -0400
Subject: fixed dragging document in filesystem to not create duplicates in
 some cases

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

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

diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 06d20f015..cb8b55cb2 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -216,7 +216,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
                 const targetDocments = DocListCast(this.dataDoc[this.props.fieldKey]);
                 const someMoved = !docDragData.userDropAction && 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 === "move" || someMoved) && docDragData.moveDocument) {
+                if ((!dropAction || 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) {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 624a0bf4a..3852987b9 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -108,7 +108,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
     protected onInternalPreDrop = (e: Event, de: DragManager.DropEvent, targetAction: dropActionType) => {
         const dragData = de.complete.docDragData;
         if (dragData) {
-            const isInTree = () => dragData.draggedDocuments.some(d => d.context === this.doc && this.childDocs.includes(d));
+            const isInTree = () => Doc.AreProtosEqual(dragData.treeViewDoc, this.props.Document) || dragData.draggedDocuments.some(d => d.context === this.doc && this.childDocs.includes(d));
             dragData.dropAction = targetAction && !isInTree() ? targetAction : this.doc === dragData?.treeViewDoc ? "same" : dragData.dropAction;
         }
     }
-- 
cgit v1.2.3-70-g09d2

