From 3573a81d334cf8cc13d19b04c6f2094c24c43932 Mon Sep 17 00:00:00 2001
From: Aubrey Li <Aubrey-Li>
Date: Thu, 3 Mar 2022 18:12:13 -0500
Subject: edit: lightbox opens tab in the same stack

---
 src/client/views/collections/CollectionDockingView.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index f543d924d..79e036a0e 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -449,7 +449,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
                     alert('cant delete the last stack');
                 }
             }));
-        stack.header?.controlsContainer.find('.lm_popout') //get the close icon
+        stack.header?.controlsContainer.find('.lm_popout') //get the popout icon
             .off('click') //unbind the current click handler
             .click(action(() => {
                 // stack.config.fixed = !stack.config.fixed;  // force the stack to have a fixed size
-- 
cgit v1.2.3-70-g09d2


From 51d7ce5f71465f2f578a08a998b2df353242ff4d Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 5 Apr 2022 13:54:26 -0400
Subject: fixes to allow dragging golden layout windows to be aborted with
 'esc'.  some code cleanup as well to avoid rebuilding golden layout when tabs
 are closed.  Fixes for undo and goldenlayout

---
 src/client/goldenLayout.js                         |  32 ++++--
 src/client/util/DragManager.ts                     |  25 ++---
 src/client/views/DocumentDecorations.tsx           |   7 +-
 src/client/views/GlobalKeyHandler.ts               |   1 +
 .../views/collections/CollectionDockingView.tsx    | 109 +++++++++++++--------
 src/client/views/collections/TabDocView.tsx        |   3 +-
 6 files changed, 108 insertions(+), 69 deletions(-)

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

diff --git a/src/client/goldenLayout.js b/src/client/goldenLayout.js
index 896237e1d..295875ef6 100644
--- a/src/client/goldenLayout.js
+++ b/src/client/goldenLayout.js
@@ -366,6 +366,7 @@
         this._nOriginalY = 0;
 
         this._bDragging = false;
+        this._bAborting = false;
 
         this._fMove = lm.utils.fnBind(this.onMouseMove, this);
         this._fUp = lm.utils.fnBind(this.onMouseUp, this);
@@ -427,6 +428,24 @@
             }
         },
 
+        AbortDrag: function () {
+            if (this._timeout != null) {
+                clearTimeout(this._timeout);
+                this._eBody.removeClass('lm_dragging');
+                this._eElement.removeClass('lm_dragging');
+                this._oDocument.find('iframe').css('pointer-events', '');
+                this._oDocument.unbind('mousemove touchmove', this._fMove);
+                this._oDocument.unbind('mouseup touchend', this._fUp);
+
+                if (this._bDragging === true) {
+                    this._bDragging = false;
+                    this._bAborting = true;
+                    this.emit('dragStop', { pageX: 0, pageY: 0 }, this._nOriginalX + this._nX);
+                    this._bAborting = false;
+                }
+            }
+        },
+
         onMouseUp: function (oEvent) {
             if (this._timeout != null) {
                 clearTimeout(this._timeout);
@@ -2178,18 +2197,18 @@
          */
         _onDrop: function () {
             this._layoutManager.dropTargetIndicator.hide();
-
+            let abortedDrop = this._dragListener._bAborting;
             /*
              * Valid drop area found
              */
-            if (this._area !== null) {
+            if (!abortedDrop && this._area !== null) {
                 this._area.contentItem._$onDrop(this._contentItem, this._area);
 
                 /**
                  * No valid drop area available at present, but one has been found before.
                  * Use it
                  */
-            } else if (this._lastValidArea !== null) {
+            } else if (!abortedDrop && this._lastValidArea !== null) {
                 this._lastValidArea.contentItem._$onDrop(this._contentItem, this._lastValidArea);
 
                 /**
@@ -2197,7 +2216,7 @@
                  * content item to its original position if a original parent is provided.
                  * (Which is not the case if the drag had been initiated by createDragSource)
                  */
-            } else if (this._originalParent) {
+            } else if (!abortedDrop && this._originalParent) {
                 this._originalParent.addChild(this._contentItem);
 
                 /**
@@ -2212,7 +2231,7 @@
             restoreScrollTops(this._contentItem.element)
             this.element.remove();
 
-            this._layoutManager.emit('itemDropped', this._contentItem);
+            !abortedDrop && this._layoutManager.emit('itemDropped', this._contentItem);
         },
 
         /**
@@ -2963,7 +2982,7 @@
             if (this.contentItem.parent.isMaximised === true) {
                 this.contentItem.parent.toggleMaximise();
             }
-            new lm.controls.DragProxy(
+            let proxy = new lm.controls.DragProxy(
                 x,
                 y,
                 this._dragListener,
@@ -2971,6 +2990,7 @@
                 this.contentItem,
                 this.header.parent
             );
+            this._layoutManager.emit('dragStart', proxy);
         },
 
         /**
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 0d6a77f71..411fc6d11 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -1,3 +1,4 @@
+import { extend } from "lodash";
 import { action } from "mobx";
 import { DateField } from "../../fields/DateField";
 import { Doc, Field, Opt } from "../../fields/Doc";
@@ -56,12 +57,7 @@ export function SetupDrag(
             if (e.shiftKey) {
                 e.persist();
                 const dragDoc = await docFunc();
-                dragDoc && DragManager.StartWindowDrag?.({
-                    pageX: e.pageX,
-                    pageY: e.pageY,
-                    preventDefault: emptyFunction,
-                    button: 0
-                }, [dragDoc]);
+                dragDoc && DragManager.StartWindowDrag?.(e, [dragDoc]);
             } else {
                 document.addEventListener("pointermove", onRowMove);
                 document.addEventListener("pointerup", onRowUp);
@@ -74,7 +70,8 @@ export function SetupDrag(
 export namespace DragManager {
     let dragDiv: HTMLDivElement;
     let dragLabel: HTMLDivElement;
-    export let StartWindowDrag: Opt<((e: any, dragDocs: Doc[]) => void)> = undefined;
+    export let StartWindowDrag: Opt<((e: { pageX: number, pageY: number }, dragDocs: Doc[], finishDrag?: (aborted: boolean) => void) => void)>;
+    export let CompleteWindowDrag: Opt<(aborted: boolean) => void>;
 
     export function Root() {
         const root = document.getElementById("root");
@@ -460,17 +457,13 @@ export namespace DragManager {
             }
             if (((e.target as any)?.className === "lm_tabs" || e?.shiftKey) && dragData.draggedDocuments.length === 1) {
                 dragData.dropAction = dragData.userDropAction || "same";
-                if (dragData.dropAction === "move" || dragData.dropAction === "same") {
-                    dragData.removeDocument?.(dragData.draggedDocuments[0]);
-                }
                 AbortDrag();
                 await finishDrag?.(new DragCompleteEvent(true, dragData));
-                DragManager.StartWindowDrag?.({
-                    pageX: e.pageX,
-                    pageY: e.pageY,
-                    preventDefault: emptyFunction,
-                    button: 0
-                }, dragData.droppedDocuments);
+                DragManager.StartWindowDrag?.(e, dragData.droppedDocuments, (aborted) => {
+                    if (!aborted && (dragData.dropAction === "move" || dragData.dropAction === "same")) {
+                        dragData.removeDocument?.(dragData.draggedDocuments[0]);
+                    }
+                });
             }
 
             const target = document.elementFromPoint(e.x, e.y);
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 8cd646935..d7ead713a 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -151,12 +151,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
     }
     onMaximizeDown = (e: React.PointerEvent) => {
         setupMoveUpEvents(this, e, () => {
-            DragManager.StartWindowDrag?.({
-                pageX: e.pageX,
-                pageY: e.pageY,
-                preventDefault: emptyFunction,
-                button: 0
-            }, [SelectionManager.Views().slice(-1)[0].rootDoc]);
+            DragManager.StartWindowDrag?.(e, [SelectionManager.Views().slice(-1)[0].rootDoc]);
             return true;
         }, emptyFunction, this.onMaximizeClick, false, false);
     }
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 1a4080d81..4a327a842 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -114,6 +114,7 @@ export class KeyManager {
                 DocumentLinksButton.StartLinkView = undefined;
                 InkStrokeProperties.Instance._controlButton = false;
                 CurrentUserUtils.SelectedTool = InkTool.None;
+                DragManager.CompleteWindowDrag?.(true);
                 var doDeselect = true;
                 if (SnappingManager.GetIsDragging()) {
                     DragManager.AbortDrag();
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 9e8374605..6931d9896 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -11,6 +11,7 @@ import { List } from '../../../fields/List';
 import { listSpec } from '../../../fields/Schema';
 import { Cast, NumCast, StrCast } from "../../../fields/Types";
 import { inheritParentAcls } from '../../../fields/util';
+import { emptyFunction } from '../../../Utils';
 import { DocServer } from "../../DocServer";
 import { Docs } from '../../documents/Documents';
 import { DocumentType } from '../../documents/DocumentTypes';
@@ -46,7 +47,7 @@ export class CollectionDockingView extends CollectionSubView() {
     private _reactionDisposer?: IReactionDisposer;
     private _lightboxReactionDisposer?: IReactionDisposer;
     private _containerRef = React.createRef<HTMLDivElement>();
-    private _flush: UndoManager.Batch | undefined;
+    public _flush: UndoManager.Batch | undefined;
     private _ignoreStateChange = "";
     public tabMap: Set<any> = new Set();
     public get initialized() { return this._goldenLayout !== null; }
@@ -62,15 +63,37 @@ export class CollectionDockingView extends CollectionSubView() {
         DragManager.StartWindowDrag = this.StartOtherDrag;
     }
 
-    public StartOtherDrag = (e: any, dragDocs: Doc[]) => {
-        !this._flush && (this._flush = UndoManager.StartBatch("golden layout drag"));
+    /**
+     * Switches from dragging a document around a freeform canvas to dragging it as a tab to be docked.
+     * 
+     * @param e fake mouse down event position data containing pageX and pageY coordinates
+     * @param dragDocs the documents to be dragged
+     * @param batch optionally an undo batch that has been started to use instead of starting a new batch
+    */
+    public StartOtherDrag = (e: { pageX: number, pageY: number }, dragDocs: Doc[], finishDrag?: (aborted: boolean) => void) => {
+        this._flush = this._flush ?? UndoManager.StartBatch("golden layout drag");
         const config = dragDocs.length === 1 ? CollectionDockingView.makeDocumentConfig(dragDocs[0]) :
-            { type: 'row', content: dragDocs.map((doc, i) => CollectionDockingView.makeDocumentConfig(doc)) };
+            { type: 'row', content: dragDocs.map(doc => CollectionDockingView.makeDocumentConfig(doc)) };
         const dragSource = this._goldenLayout.createDragSource(document.createElement("div"), config);
-        //dragSource._dragListener.on("dragStop", dragSource.destroy);
-        dragSource._dragListener.onMouseDown(e);
+        this.tabDragStart(dragSource, finishDrag);
+        dragSource._dragListener.onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, button: 0 });
     }
 
+    tabItemDropped = () => DragManager.CompleteWindowDrag?.(false);
+    tabDragStart = (proxy: any, finishDrag?: (aborted: boolean) => void) => {
+        DragManager.CompleteWindowDrag = (aborted: boolean) => {
+            if (aborted) {
+                proxy._dragListener.AbortDrag();
+                if (this._flush) {
+                    this._flush.cancel();  // cancel the undo change being logged
+                    this._flush = undefined;
+                    this.setupGoldenLayout(); // restore golden layout to where it was before the drag (this is a no-op when using StartOtherDrag because the proxy dragged item was never in the golden layout)
+                }
+                DragManager.CompleteWindowDrag = undefined;
+            }
+            finishDrag?.(aborted);
+        }
+    }
     @undoBatch
     public CloseFullScreen = () => {
         this._goldenLayout._maximisedItem?.toggleMaximise();
@@ -106,7 +129,6 @@ export class CollectionDockingView extends CollectionSubView() {
         docconfig.callDownwards('_$init');
         instance._goldenLayout._$maximiseItem(docconfig);
         instance._goldenLayout.emit('stateChanged');
-        instance._ignoreStateChange = JSON.stringify(instance._goldenLayout.toConfig());
         instance.stateChanged();
         return true;
     }
@@ -255,7 +277,6 @@ export class CollectionDockingView extends CollectionSubView() {
     layoutChanged() {
         this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]);
         this._goldenLayout.emit('stateChanged');
-        this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig());
         this.stateChanged();
         return true;
     }
@@ -294,6 +315,9 @@ export class CollectionDockingView extends CollectionSubView() {
                 }
             }
             this._goldenLayout.init();
+            this._goldenLayout.root.layoutManager.on('itemDropped', this.tabItemDropped);
+            this._goldenLayout.root.layoutManager.on('dragStart', this.tabDragStart)
+            this._goldenLayout.root.layoutManager.on('activeContentItemChanged', this.stateChanged);
         }
     }
 
@@ -335,13 +359,12 @@ export class CollectionDockingView extends CollectionSubView() {
     @action
     onPointerUp = (e: MouseEvent): void => {
         window.removeEventListener("pointerup", this.onPointerUp);
-        if (this._flush) {
-            setTimeout(() => {
-                CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig());
-                this.stateChanged();
-                this._flush?.end();
-                this._flush = undefined;
-            }, 10);
+        const flush = this._flush;
+        this._flush = undefined;
+        if (flush) {
+            DragManager.CompleteWindowDrag = undefined;
+            if (!this.stateChanged()) flush.cancel();
+            else flush.end();
         }
     }
 
@@ -352,9 +375,12 @@ export class CollectionDockingView extends CollectionSubView() {
             hitFlyout = (par.className === "dockingViewButtonSelector");
         }
         if (!hitFlyout) {
+            const htmlTarget = e.target as HTMLElement;
             window.addEventListener("mouseup", this.onPointerUp);
-            if (!(e.target as HTMLElement).closest("*.lm_content") && ((e.target as HTMLElement).closest("*.lm_tab") || (e.target as HTMLElement).closest("*.lm_stack"))) {
-                this._flush = UndoManager.StartBatch("golden layout edit");
+            if (!htmlTarget.closest("*.lm_content") && (htmlTarget.closest("*.lm_tab") || htmlTarget.closest("*.lm_stack"))) {
+                if (htmlTarget.className !== "lm_close_tab") {
+                    this._flush = UndoManager.StartBatch("golden layout edit");
+                }
             }
         }
         if (!e.nativeEvent.cancelBubble && !InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE) &&
@@ -388,38 +414,43 @@ export class CollectionDockingView extends CollectionSubView() {
 
     @action
     stateChanged = () => {
+        this._ignoreStateChange = JSON.stringify(this._goldenLayout.toConfig());
         const json = JSON.stringify(this._goldenLayout.toConfig());
         const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g);
         const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", ""));
         const docs = !docids ? [] : docids.map(id => DocServer.GetCachedRefField(id)).filter(f => f).map(f => f as Doc);
-
-        this.props.Document.dockingConfig = json;
-        setTimeout(async () => {
-            const sublists = await DocListCastAsync(this.props.Document[this.props.fieldKey]);
-            const tabs = sublists && Cast(sublists[0], Doc, null);
-            // const other = sublists && Cast(sublists[1], Doc, null);
-            const tabdocs = await DocListCastAsync(tabs?.data);
-            // const otherdocs = await DocListCastAsync(other?.data);
-            if (tabs) {
-                tabs.data = new List<Doc>(docs);
-                // DocListCast(tabs.aliases).forEach(tab => tab !== tabs && (tab.data = new List<Doc>(docs)));
-            }
-            // const otherSet = new Set<Doc>();
-            // otherdocs?.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc));
-            // tabdocs?.filter(doc => !docs.includes(doc) && doc.type !== DocumentType.KVP).forEach(doc => otherSet.add(doc));
-            // const vals = Array.from(otherSet.values()).filter(val => val instanceof Doc).map(d => d).filter(d => d.type !== DocumentType.KVP);
-            // this.props.Document[DataSym][this.props.fieldKey + "-all"] = new List<Doc>([...docs, ...vals]);
-            // if (other) {
-            //     other.data = new List<Doc>(vals);
-            //     // DocListCast(other.aliases).forEach(tab => tab !== other && (tab.data = new List<Doc>(vals)));
-            // }
-        }, 0);
+        const changesMade = this.props.Document.dockingConfig !== json;
+        if (changesMade && !this._flush) {
+            this.props.Document.dockingConfig = json;
+            setTimeout(async () => {
+                const sublists = await DocListCastAsync(this.props.Document[this.props.fieldKey]);
+                const tabs = sublists && Cast(sublists[0], Doc, null);
+                // const other = sublists && Cast(sublists[1], Doc, null);
+                const tabdocs = await DocListCastAsync(tabs?.data);
+                // const otherdocs = await DocListCastAsync(other?.data);
+                if (tabs) {
+                    tabs.data = new List<Doc>(docs);
+                    // DocListCast(tabs.aliases).forEach(tab => tab !== tabs && (tab.data = new List<Doc>(docs)));
+                }
+                // const otherSet = new Set<Doc>();
+                // otherdocs?.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc));
+                // tabdocs?.filter(doc => !docs.includes(doc) && doc.type !== DocumentType.KVP).forEach(doc => otherSet.add(doc));
+                // const vals = Array.from(otherSet.values()).filter(val => val instanceof Doc).map(d => d).filter(d => d.type !== DocumentType.KVP);
+                // this.props.Document[DataSym][this.props.fieldKey + "-all"] = new List<Doc>([...docs, ...vals]);
+                // if (other) {
+                //     other.data = new List<Doc>(vals);
+                //     // DocListCast(other.aliases).forEach(tab => tab !== other && (tab.data = new List<Doc>(vals)));
+                // }
+            }, 0);
+        }
+        return changesMade;
     }
 
     tabDestroyed = (tab: any) => {
         this.tabMap.delete(tab);
         tab._disposers && Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
         tab.reactComponents?.forEach((ele: any) => ReactDOM.unmountComponentAtNode(ele));
+        this.stateChanged();
     }
     tabCreated = (tab: any) => {
         tab.contentItem.element[0]?.firstChild?.firstChild?.InitTab?.(tab);  // have to explicitly initialize tabs that reuse contents from previous tabs (ie, when dragging a tab around a new tab is created for the old content)
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 8b5022593..ad5c0efb3 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -190,7 +190,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
                     Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", doc, undefined, true, true);
                     SelectionManager.DeselectAll();
-                    tab.contentItem.remove();
+                    UndoManager.RunInBatch(() => tab.contentItem.remove(), "delete tab");
                 });
         }
     }
@@ -277,7 +277,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     private onActiveContentItemChanged(contentItem: any) {
         if (!contentItem || (this.stack === contentItem.parent && ((contentItem?.tab === this.tab && !this._isActive) || (contentItem?.tab !== this.tab && this._isActive)))) {
             this._activated = this._isActive = !contentItem || contentItem?.tab === this.tab;
-            (CollectionDockingView.Instance as any)._goldenLayout?.isInitialised && CollectionDockingView.Instance.stateChanged();
             !this._isActive && this._document && Doc.UnBrushDoc(this._document); // bcz: bad -- trying to simulate a pointer leave event when a new tab is opened up on top of an existing one.
         }
     }
-- 
cgit v1.2.3-70-g09d2


From fd58a5f8598815ab1ab3893e60973654a59a52c1 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 12 Apr 2022 10:54:28 -0400
Subject: cleaned up errors/warnings.   fixed dragging to turn off pointer
 events on whatever's being dragged.

---
 src/client/util/DocumentManager.ts                             | 10 ++++++----
 src/client/util/DragManager.ts                                 |  2 +-
 src/client/views/StyleProvider.tsx                             |  4 +++-
 src/client/views/collections/CollectionDockingView.tsx         |  4 ++--
 .../collections/collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 src/client/views/nodes/CollectionFreeFormDocumentView.tsx      |  4 ++--
 src/client/views/nodes/LabelBox.tsx                            |  7 +------
 src/client/views/nodes/PDFBox.tsx                              |  6 +++---
 src/client/views/nodes/VideoBox.tsx                            |  2 +-
 src/client/views/nodes/formattedText/FormattedTextBox.tsx      |  2 +-
 10 files changed, 21 insertions(+), 22 deletions(-)

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

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 6076de055..1d603e18f 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -169,10 +169,12 @@ export class DocumentManager {
         const getFirstDocView = LightboxView.LightboxDoc ? DocumentManager.Instance.getLightboxDocumentView : DocumentManager.Instance.getFirstDocumentView;
         const docView = getFirstDocView(targetDoc, originatingDoc);
         const wasHidden = targetDoc.hidden;  // 
-        if (wasHidden) runInAction(() => {
-            targetDoc.hidden = false;
-            docView?.props.bringToFront(targetDoc);
-        });  // if the target is hidden, un-hide it here.
+        if (wasHidden) {
+            runInAction(() => {
+                targetDoc.hidden = false;
+                docView?.props.bringToFront(targetDoc);
+            });  // if the target is hidden, un-hide it here.
+        }
         const focusAndFinish = (didFocus: boolean) => {
             if (originatingDoc?.isPushpin) {
                 if (!didFocus && !wasHidden) {  // don't toggle the hidden state if the doc was already un-hidden as part of this document traversal
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 94a09eac4..13e5940d6 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -405,7 +405,7 @@ export namespace DragManager {
                 Array.from(pdfBox).filter(pb => pb.width && pb.height).map((pb, i) => pb.getContext('2d')!.drawImage(pdfBoxSrc[i], 0, 0));
             }
             [dragElement, ...Array.from(dragElement.getElementsByTagName('*'))].forEach(ele =>
-                ele.hasAttribute("style") && ((ele as any).style.pointerEvents = "none"));
+                (ele as any).style && ((ele as any).style.pointerEvents = "none"));
 
             dragDiv.appendChild(dragElement);
             if (dragElement !== ele) {
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 2ce78f64f..9803f9782 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -149,7 +149,9 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                                     (doc?._isGroup ? undefined :
                                         StrCast((props?.renderDepth || 0) > 0 ?
                                             Doc.UserDoc().activeCollectionNestedBackground :
-                                            Doc.UserDoc().activeCollectionBackground ?? (darkScheme() ? Colors.BLACK : Colors.WHITE))
+                                            Doc.UserDoc().activeCollectionBackground ?? (darkScheme() ?
+                                                Colors.BLACK :
+                                                "linear-gradient(#065fff, #85c1f9)"))
                                     ));
                     break;
                 //if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)";
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 6931d9896..e95371aaa 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -92,7 +92,7 @@ export class CollectionDockingView extends CollectionSubView() {
                 DragManager.CompleteWindowDrag = undefined;
             }
             finishDrag?.(aborted);
-        }
+        };
     }
     @undoBatch
     public CloseFullScreen = () => {
@@ -316,7 +316,7 @@ export class CollectionDockingView extends CollectionSubView() {
             }
             this._goldenLayout.init();
             this._goldenLayout.root.layoutManager.on('itemDropped', this.tabItemDropped);
-            this._goldenLayout.root.layoutManager.on('dragStart', this.tabDragStart)
+            this._goldenLayout.root.layoutManager.on('dragStart', this.tabDragStart);
             this._goldenLayout.root.layoutManager.on('activeContentItemChanged', this.stateChanged);
         }
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 04beed541..9b0acffdf 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1417,7 +1417,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     updateIcon = () => {
         this.props.docViewPath().lastElement().ContentDiv!.style.width = (this.layoutDoc[WidthSym]()).toString();
         this.props.docViewPath().lastElement().ContentDiv!.style.height = (this.layoutDoc[HeightSym]()).toString();
-        var htmlString = this._mainCont && new XMLSerializer().serializeToString(this.props.docViewPath().lastElement().ContentDiv!);
+        const htmlString = this._mainCont && new XMLSerializer().serializeToString(this.props.docViewPath().lastElement().ContentDiv!);
         this.props.docViewPath().lastElement().ContentDiv!.style.width = "";
         this.props.docViewPath().lastElement().ContentDiv!.style.height = "";
         const nativeWidth = this.layoutDoc[WidthSym]();
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 7fb2c235a..3e35039e3 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -168,8 +168,8 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             PanelWidth: this.panelWidth,
             PanelHeight: this.panelHeight,
         };
-        var background = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-        const mixBlendMode = StrCast(this.layoutDoc.mixBlendMode) as any || (typeof background === "string" && background && DashColor(background).alpha() !== 1 ? "multiply" : undefined);
+        const background = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+        const mixBlendMode = StrCast(this.layoutDoc.mixBlendMode) as any || (typeof background === "string" && background && (!background.startsWith("linear") && DashColor(background).alpha() !== 1) ? "multiply" : undefined);
         return <div className={"collectionFreeFormDocumentView-container"}
             style={{
                 outline: this.Highlight ? "orange solid 2px" : "",
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index 3405a7635..d539ca9b8 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -30,11 +30,6 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro
 
     componentDidMount() {
         this.props.setContentView?.(this);
-        console.log("MOUNTING")
-    }
-
-    componentDidUpdate() {
-        console.log("UPDATING")
     }
 
     getTitle() {
@@ -89,7 +84,7 @@ export class LabelBox extends ViewBoxBaseComponent<(FieldViewProps & LabelBoxPro
             verticalAlign: "center",
             textAlign: "center",
             whiteSpace: "nowrap"
-        })
+        });
     }
     // (!missingParams || !missingParams.length ? "" : "(" + missingParams.map(m => m + ":").join(" ") + ")")
     render() {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 3f1771e68..c73823a2b 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -63,7 +63,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         }
         if (oldDiv instanceof HTMLCanvasElement) {
             const canvas = oldDiv as HTMLCanvasElement;
-            var img = document.createElement('img'); // create a Image Element
+            const img = document.createElement('img'); // create a Image Element
             img.src = canvas.toDataURL();   //image source
             img.style.width = canvas.style.width;
             img.style.height = canvas.style.height;
@@ -79,8 +79,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
         const newDiv = docViewContent.cloneNode(true) as HTMLDivElement;
         newDiv.style.width = (this.layoutDoc[WidthSym]()).toString();
         newDiv.style.height = (this.layoutDoc[HeightSym]()).toString();
-        this.replaceCanvases(docViewContent, newDiv)
-        var htmlString = this._pdfViewer?._mainCont.current && new XMLSerializer().serializeToString(newDiv);
+        this.replaceCanvases(docViewContent, newDiv);
+        const htmlString = this._pdfViewer?._mainCont.current && new XMLSerializer().serializeToString(newDiv);
         const nativeWidth = this.layoutDoc[WidthSym]();
         const nativeHeight = this.layoutDoc[HeightSym]();
 
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index b7b8ce064..c31d38b0d 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -265,7 +265,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
             this.dataDoc.icon = new ImageField(returnedfilename);
             this.dataDoc["icon-nativeWidth"] = this.layoutDoc[WidthSym]();
             this.dataDoc["icon-nativeHeight"] = this.layoutDoc[HeightSym]();
-        }
+        };
         this.Snapshot(undefined, undefined, makeIcon);
     }
 
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index ec88b8d1d..b6713d878 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -364,7 +364,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     }
 
     updateTitle = () => {
-        const title = StrCast(this.dataDoc.title)
+        const title = StrCast(this.dataDoc.title);
         if (!this.props.dontRegisterView &&  // (this.props.Document.isTemplateForField === "text" || !this.props.Document.isTemplateForField) && // only update the title if the data document's data field is changing
             (title.startsWith("-") || title.startsWith("@")) && this._editorView && !this.dataDoc["title-custom"] &&
             (Doc.LayoutFieldKey(this.rootDoc) === this.fieldKey || this.fieldKey === "text")) {
-- 
cgit v1.2.3-70-g09d2


From 5f297a17b38bdcd4d3928137daacf14fe2fbec9f Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 25 Apr 2022 21:45:20 -0400
Subject: put snapshot dash in novice mode.  fixed undo for snapshot/new
 dashboard.  changed titling of snapshots to use {#}.  no current UI for
 cloning dashboards.

---
 src/Utils.ts                                       |  6 +++++
 .../views/collections/CollectionDockingView.tsx    |  7 +++---
 src/client/views/topbar/TopBar.tsx                 | 26 +++++++++++++---------
 src/fields/Doc.ts                                  |  7 ++++--
 4 files changed, 30 insertions(+), 16 deletions(-)

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

diff --git a/src/Utils.ts b/src/Utils.ts
index d1d400de7..38eb51529 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -399,6 +399,12 @@ export function timenow() {
     return now.toLocaleDateString() + ' ' + h + ':' + m + ' ' + ampm;
 }
 
+export function incrementTitleCopy(title: string) {
+    const numstr = title.match(/.*(\{([0-9]*)\})+/);
+    const copyNumStr = `{${1 + (numstr ? (+numstr[2]) : 0)}}`;
+    return (numstr ? title.replace(numstr[1], "") : title) + copyNumStr;
+}
+
 export function formatTime(time: number) {
     time = Math.round(time);
     const hours = Math.floor(time / 60 / 60);
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index e95371aaa..64a5f38d4 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -11,7 +11,7 @@ import { List } from '../../../fields/List';
 import { listSpec } from '../../../fields/Schema';
 import { Cast, NumCast, StrCast } from "../../../fields/Types";
 import { inheritParentAcls } from '../../../fields/util';
-import { emptyFunction } from '../../../Utils';
+import { emptyFunction, incrementTitleCopy } from '../../../Utils';
 import { DocServer } from "../../DocServer";
 import { Docs } from '../../documents/Documents';
 import { DocumentType } from '../../documents/DocumentTypes';
@@ -390,7 +390,6 @@ export class CollectionDockingView extends CollectionSubView() {
     }
 
     public static async Copy(doc: Doc, clone = false) {
-        clone = !Doc.UserDoc().noviceMode;
         let json = StrCast(doc.dockingConfig);
         if (clone) {
             const cloned = (await Doc.MakeClone(doc));
@@ -403,13 +402,13 @@ export class CollectionDockingView extends CollectionSubView() {
         const origtabs = origtabids.map(id => DocServer.GetCachedRefField(id)).filter(f => f).map(f => f as Doc);
         const newtabs = origtabs.map(origtab => {
             const origtabdocs = DocListCast(origtab.data);
-            const newtab = origtabdocs.length ? Doc.MakeCopy(origtab, true) : Doc.MakeAlias(origtab);
+            const newtab = origtabdocs.length ? Doc.MakeCopy(origtab, true, undefined, true) : Doc.MakeAlias(origtab);
             const newtabdocs = origtabdocs.map(origtabdoc => Doc.MakeAlias(origtabdoc));
             newtabdocs.length && (Doc.GetProto(newtab).data = new List<Doc>(newtabdocs));
             json = json.replace(origtab[Id], newtab[Id]);
             return newtab;
         });
-        return Docs.Create.DockDocument(newtabs, json, { title: "Snapshot: " + doc.title });
+        return Docs.Create.DockDocument(newtabs, json, { title: incrementTitleCopy(StrCast(doc.title)) });
     }
 
     @action
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index d5254e315..0af7de6af 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -7,7 +7,7 @@ import { StrCast } from '../../../fields/Types';
 import { Utils } from '../../../Utils';
 import { CurrentUserUtils } from "../../util/CurrentUserUtils";
 import { SettingsManager } from "../../util/SettingsManager";
-import { undoBatch } from "../../util/UndoManager";
+import { undoBatch, UndoManager } from "../../util/UndoManager";
 import { Borders, Colors } from "../global/globalEnums";
 import "./TopBar.scss";
 
@@ -33,30 +33,36 @@ export class TopBar extends React.Component {
                     </div>
                     <div className="topbar-center" >
                         <div className="topbar-lozenge-dashboard">
-                            <select className="topbar-dashSelect" onChange={e => CurrentUserUtils.openDashboard(Doc.UserDoc(), myDashboards[Number(e.target.value)])}
+                            <select className="topbar-dashSelect" onChange={undoBatch(e => CurrentUserUtils.openDashboard(Doc.UserDoc(), myDashboards[Number(e.target.value)]))}
                                 value={myDashboards.indexOf(CurrentUserUtils.ActiveDashboard)}
                                 style={{ color: Colors.WHITE }}>
                                 {myDashboards.map((dash, i) => <option key={dash[Id]} value={i}> {StrCast(dash.title)} </option>)}
                             </select>
                         </div>
                         <div className="topbar-dashboards">
-                            <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.createNewDashboard(Doc.UserDoc()))}
-                            >
-                                {"New"}<FontAwesomeIcon icon="plus"></FontAwesomeIcon>
+                            <div className="topbar-icon" onClick={async () => {
+                                const batch = UndoManager.StartBatch("new dash");
+                                await CurrentUserUtils.createNewDashboard(Doc.UserDoc());
+                                batch.end();
+                            }}>
+                                {"New"}<FontAwesomeIcon icon="plus" />
                             </div>
-                            {Doc.UserDoc().noviceMode ? (null) : <div className="topbar-icon" onClick={undoBatch(() => CurrentUserUtils.snapshotDashboard(Doc.UserDoc()))}
-                            >
-                                {"Snapshot"}<FontAwesomeIcon icon="camera"></FontAwesomeIcon>
+                            {<div className="topbar-icon" onClick={async () => {
+                                const batch = UndoManager.StartBatch("snapshot");
+                                await CurrentUserUtils.snapshotDashboard(Doc.UserDoc());
+                                batch.end();
+                            }}>
+                                {"Snapshot"}<FontAwesomeIcon icon="camera" />
                             </div>}
                         </div>
                     </div>
                     <div className="topbar-right" >
                         <div className="topbar-icon" onClick={() => window.open(
                             "https://brown-dash.github.io/Dash-Documentation/", "_blank")}>
-                            {"Help"}<FontAwesomeIcon icon="question-circle"></FontAwesomeIcon>
+                            {"Help"}<FontAwesomeIcon icon="question-circle" />
                         </div>
                         <div className="topbar-icon" onClick={() => SettingsManager.Instance.open()}>
-                            {"Settings"}<FontAwesomeIcon icon="cog"></FontAwesomeIcon>
+                            {"Settings"}<FontAwesomeIcon icon="cog" />
                         </div>
 
                     </div>
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 63af8401c..50e5fcbc4 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -11,7 +11,7 @@ import { scriptingGlobal, ScriptingGlobals } from "../client/util/ScriptingGloba
 import { SelectionManager } from "../client/util/SelectionManager";
 import { afterDocDeserialize, autoObject, Deserializable, SerializationHelper } from "../client/util/SerializationHelper";
 import { UndoManager } from "../client/util/UndoManager";
-import { DashColor, intersectRect, Utils } from "../Utils";
+import { DashColor, incrementTitleCopy, intersectRect, Utils } from "../Utils";
 import { DateField } from "./DateField";
 import { Copy, HandleUpdate, Id, OnUpdate, Parent, Self, SelfProxy, ToScriptString, ToString, Update } from "./FieldSymbols";
 import { List } from "./List";
@@ -770,7 +770,7 @@ export namespace Doc {
         return overwrite;
     }
 
-    export function MakeCopy(doc: Doc, copyProto: boolean = false, copyProtoId?: string): Doc {
+    export function MakeCopy(doc: Doc, copyProto: boolean = false, copyProtoId?: string, retitle = false): Doc {
         const copy = new Doc(copyProtoId, true);
         const exclude = Cast(doc.cloneFieldFilter, listSpec("string"), []);
         Object.keys(doc).forEach(key => {
@@ -806,6 +806,9 @@ export namespace Doc {
         }
         copy.context = undefined;
         Doc.UserDoc().defaultAclPrivate && (copy["acl-Public"] = "Not Shared");
+        if (retitle) {
+            copy.title = incrementTitleCopy(StrCast(copy.title));
+        }
         return copy;
     }
 
-- 
cgit v1.2.3-70-g09d2


From 09c7ee4120f48e212f9b64fd3e307c8ce49e0cfd Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 16 May 2022 19:33:08 -0400
Subject: fixed snapshot to set 'context' of new aliases.

---
 src/client/views/collections/CollectionDockingView.tsx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 64a5f38d4..30f60bba6 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -404,7 +404,10 @@ export class CollectionDockingView extends CollectionSubView() {
             const origtabdocs = DocListCast(origtab.data);
             const newtab = origtabdocs.length ? Doc.MakeCopy(origtab, true, undefined, true) : Doc.MakeAlias(origtab);
             const newtabdocs = origtabdocs.map(origtabdoc => Doc.MakeAlias(origtabdoc));
-            newtabdocs.length && (Doc.GetProto(newtab).data = new List<Doc>(newtabdocs));
+            if (newtabdocs.length) {
+                Doc.GetProto(newtab).data = new List<Doc>(newtabdocs);
+                newtabdocs.forEach(ntab => ntab.context = newtab);
+            }
             json = json.replace(origtab[Id], newtab[Id]);
             return newtab;
         });
-- 
cgit v1.2.3-70-g09d2


From d50b851d8e92797d214fc35cf243bfb29e970b36 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 23 May 2022 21:58:26 -0400
Subject: simplified dashboards by getting rid of confusing
 on-screen/off-screen tabs.  Now off screen tabs appear in the header bar
 which is not currently specific to a dashboard.

---
 src/client/documents/Documents.ts                  |  4 +-
 src/client/util/CurrentUserUtils.ts                | 33 +--------------
 src/client/views/MainView.tsx                      |  4 +-
 .../views/collections/CollectionDockingView.tsx    | 48 +++++++++++++++++-----
 src/client/views/collections/TabDocView.tsx        |  3 +-
 5 files changed, 43 insertions(+), 49 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 6fa467368..c3b6953b5 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -905,9 +905,7 @@ export namespace Docs {
         }
 
         export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) {
-            const tabs = TreeDocument(documents, { title: "On-Screen Tabs", childDontRegisterViews: true, freezeChildren: "remove|add", treeViewExpandedViewLock: true, treeViewExpandedView: "data", _fitWidth: true, system: true, isFolder: true });
-            const all = TreeDocument([], { title: "Off-Screen Tabs", childDontRegisterViews: true, freezeChildren: "add", treeViewExpandedViewLock: true, treeViewExpandedView: "data", system: true, isFolder: true });
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List([tabs, all]), { freezeChildren: "remove|add", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id);
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { freezeChildren: "remove|add", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id);
         }
 
         export function DirectoryImportDocument(options: DocumentOptions = {}) {
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 1e42b9073..9212d8ed9 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1172,22 +1172,8 @@ export class CurrentUserUtils {
         freeformDoc.context = dashboardDoc;
 
         // switching the tabs from the datadoc to the regular doc
-        const dashboardTabs = dashboardDoc[DataSym].data;
-        dashboardDoc[DataSym].data = new List<Doc>();
-        dashboardDoc.data = dashboardTabs;
-
-        // collating all docs on the dashboard to make a data-all field
-        const allDocs = new List<Doc>();
-        const allDocs2 = new List<Doc>(); // Array.from, spread, splice all cause so stack or acl issues for some reason
-        DocListCast(dashboardTabs).forEach(doc => {
-            const tabDocs = DocListCast(doc.data);
-            allDocs.push(...tabDocs);
-            allDocs2.push(...tabDocs);
-        });
-        dashboardDoc[DataSym]["data-all"] = allDocs;
-        dashboardDoc["data-all"] = allDocs2;
-        DocListCast(dashboardDoc.data).forEach(doc => doc.dashboard = dashboardDoc);
-        DocListCast(dashboardDoc.data)[1].data = ComputedField.MakeFunction(`dynamicOffScreenDocs(self.dashboard)`) as any;
+        const dashboardTabs = DocListCast(dashboardDoc[DataSym].data);
+        dashboardDoc.data = new List<Doc>(dashboardTabs);
 
         userDoc.activePresentation = presentation;
 
@@ -1258,21 +1244,6 @@ ScriptingGlobals.add(function addToDashboards(dashboard: Doc) {
 },
     "adds Dashboard to set of Dashboards");
 
-/**
- * Dynamically computes which docs should be rendered in the off-screen tabs tree of a dashboard.
- */
-ScriptingGlobals.add(function dynamicOffScreenDocs(dashboard: Doc) {
-    if (dashboard[DataSym] instanceof Doc) {
-        const allDocs = DocListCast(dashboard["data-all"]);
-        const onScreenTab = DocListCast(dashboard.data)[0];
-        const onScreenDocs = DocListCast(onScreenTab.data);
-        return new List<Doc>(allDocs.reduce((result: Doc[], doc) => {
-            !onScreenDocs.includes(doc) && !onScreenDocs.includes(doc.aliasOf as Doc) && (result.push(doc));
-            return result;
-        }, []));
-    }
-    return [];
-});
 ScriptingGlobals.add(function selectedDocumentType(docType?: DocumentType, colType?: CollectionViewType, checkParent?: boolean) {
     let selected = SelectionManager.Docs().length ? SelectionManager.Docs()[0] : undefined;
     if (selected && checkParent) {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 69e394790..f3dc2cf85 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -92,7 +92,7 @@ export class MainView extends React.Component {
     @computed private get headerBarDoc() { return this.userDoc ? CurrentUserUtils.MyHeaderBarDoc : CurrentUserUtils.MyHeaderBarDoc; }
     @computed public get mainFreeform(): Opt<Doc> { return (docs => (docs?.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); }
 
-    headerBarDocWidth = () => this._dashUIWidth;
+    headerBarDocWidth = () => this.mainDocViewWidth();
     headerBarDocHeight = () => CurrentUserUtils.headerBarHeight ?? 0;
     topMenuHeight = () => 35;
     topMenuWidth = returnZero; // value is ignored ...
@@ -102,7 +102,7 @@ export class MainView extends React.Component {
     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();
+    mainDocViewWidth = () => this._dashUIWidth - this.propertiesWidth() - this.leftMenuWidth() - this.leftMenuFlyoutWidth();
     mainDocViewHeight = () => this._dashUIHeight - this.headerBarDocHeight();
 
     componentDidMount() {
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 30f60bba6..1d65256a6 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -81,6 +81,8 @@ export class CollectionDockingView extends CollectionSubView() {
 
     tabItemDropped = () => DragManager.CompleteWindowDrag?.(false);
     tabDragStart = (proxy: any, finishDrag?: (aborted: boolean) => void) => {
+        const dashDoc = proxy?._contentItem?.tab?.DashDoc as Doc;
+        dashDoc && (DragManager.DocDragData = new DragManager.DocumentDragData([proxy._contentItem.tab.DashDoc]));
         DragManager.CompleteWindowDrag = (aborted: boolean) => {
             if (aborted) {
                 proxy._dragListener.AbortDrag();
@@ -90,6 +92,8 @@ export class CollectionDockingView extends CollectionSubView() {
                     this.setupGoldenLayout(); // restore golden layout to where it was before the drag (this is a no-op when using StartOtherDrag because the proxy dragged item was never in the golden layout)
                 }
                 DragManager.CompleteWindowDrag = undefined;
+            } else {
+                DragManager.DocDragData?.droppedDocuments.forEach(doc => this.addToTabDocList(doc));
             }
             finishDrag?.(aborted);
         };
@@ -100,12 +104,43 @@ export class CollectionDockingView extends CollectionSubView() {
         this.stateChanged();
     }
 
+    addToTabDocList = (document: Doc) => {
+        const instance = CollectionDockingView.Instance;
+        if (instance) {
+            const docList = DocListCast(instance.props.Document[DataSym].data);
+            // adds the doc of the newly created tab to the data-all field if it doesn't already include that doc or one of its aliases
+            !docList.includes(document) && !docList.includes(document.aliasOf as Doc) && Doc.AddDocToList(instance.props.Document[DataSym], "data", document);
+            // adds an alias of the doc to the data-all field of the layoutdocs of the aliases
+            DocListCast(instance.props.Document.aliases).forEach(alias => {
+                const aliasDocList = DocListCast(alias.data);
+                // if aliasDocList contains the alias, don't do anything
+                // otherwise add the original or an alias depending on whether the doc you're looking at is the current doc or a different alias
+                !DocListCast(document.aliases).some(a => aliasDocList.includes(a)) && Doc.AddDocToList(alias, "data", document);//alias !== instance.props.Document ? Doc.MakeAlias(document) : document);
+            });
+        }
+    }
+    removeFromTabDocList = (document: Doc) => {
+        const instance = CollectionDockingView.Instance;
+        if (instance) {
+            // adds the doc of the newly created tab to the data-all field if it doesn't already include that doc or one of its aliases
+            Doc.RemoveDocFromList(instance.props.Document[DataSym], "data", document);
+            // adds an alias of the doc to the data-all field of the layoutdocs of the aliases
+            DocListCast(instance.props.Document.aliases).forEach(alias => {
+                // if aliasDocList contains the alias, don't do anything
+                // otherwise add the original or an alias depending on whether the doc you're looking at is the current doc or a different alias
+                Doc.RemoveDocFromList(alias, "data", document);//alias !== instance.props.Document ? Doc.MakeAlias(document) : document);
+            });
+            document.type !== DocumentType.KVP && Doc.AddDocToList(CurrentUserUtils.MyHeaderBarDoc, "data", document);
+        }
+    }
+
     @undoBatch
     public static CloseSplit(document: Opt<Doc>, panelName?: string): boolean {
         const tab = Array.from(CollectionDockingView.Instance.tabMap.keys()).find((tab) => panelName ? tab.contentItem.config.props.panelName === panelName : tab.DashDoc === document);
         if (tab) {
             const j = tab.header.parent.contentItems.indexOf(tab.contentItem);
             if (j !== -1) {
+                CollectionDockingView.Instance.removeFromTabDocList(tab.dashDoc as Doc);
                 tab.header.parent.contentItems[j].remove();
                 return CollectionDockingView.Instance.layoutChanged();
             }
@@ -185,16 +220,7 @@ export class CollectionDockingView extends CollectionSubView() {
         const instance = CollectionDockingView.Instance;
         if (!instance) return false;
         else {
-            const docList = DocListCast(instance.props.Document[DataSym]["data-all"]);
-            // adds the doc of the newly created tab to the data-all field if it doesn't already include that doc or one of its aliases
-            !docList.includes(document) && !docList.includes(document.aliasOf as Doc) && Doc.AddDocToList(instance.props.Document[DataSym], "data-all", document);
-            // adds an alias of the doc to the data-all field of the layoutdocs of the aliases
-            DocListCast(instance.props.Document[DataSym].aliases).forEach(alias => {
-                const aliasDocList = DocListCast(alias["data-all"]);
-                // if aliasDocList contains the alias, don't do anything
-                // otherwise add the original or an alias depending on whether the doc you're looking at is the current doc or a different alias
-                !DocListCast(document.aliases).some(a => aliasDocList.includes(a)) && Doc.AddDocToList(alias, "data-all", document);//alias !== instance.props.Document ? Doc.MakeAlias(document) : document);
-            });
+            instance.addToTabDocList(document);
         }
         const docContentConfig = CollectionDockingView.makeDocumentConfig(document, panelName);
 
@@ -477,7 +503,7 @@ export class CollectionDockingView extends CollectionSubView() {
                 //if (confirm('really close this?')) {
                 if (!stack.parent.parent.isRoot || stack.parent.contentItems.length > 1) {
                     stack.remove();
-                    stack.contentItems.forEach((contentItem: any) => Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", contentItem.tab.DashDoc, undefined, true, true));
+                    stack.contentItems.forEach((contentItem: any) => CollectionDockingView.Instance.removeFromTabDocList(contentItem.tab.DashDoc));
                 } else {
                     alert('cant delete the last stack');
                 }
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 0070d0b9d..88d14fdfe 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -180,8 +180,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             tab.closeElement.off('click') //unbind the current click handler
                 .click(function () {
                     Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
-                    Doc.AddDocToList(CurrentUserUtils.MyHeaderBarDoc, "data", doc);
-                    Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", doc, undefined, true, true);
+                    CollectionDockingView.Instance?.removeFromTabDocList(doc);
                     SelectionManager.DeselectAll();
                     UndoManager.RunInBatch(() => tab.contentItem.remove(), "delete tab");
                 });
-- 
cgit v1.2.3-70-g09d2


From 76d737a05093e4132f2ab56630c4003879747ef9 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 26 May 2022 15:36:32 -0400
Subject: removed setting 'data' field of docking views on aliases.    assigned
 acl's to delegates to match prototype.  changed how documents are created to
 make sure acl's are set first so that, when sharing, remote clients will get
 the ACLs first and not render documents transiently when they don't have
 permissions.  turned off inheriting ACL's from outer collection

---
 src/client/documents/Documents.ts                      | 15 +++++++++------
 src/client/util/CurrentUserUtils.ts                    |  3 ---
 src/client/views/collections/CollectionDockingView.tsx | 17 ++---------------
 src/client/views/global/globalCssVariables.scss        |  2 +-
 src/fields/Doc.ts                                      |  1 +
 src/fields/util.ts                                     |  3 ++-
 6 files changed, 15 insertions(+), 26 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index ed37c48dc..8d29bcebe 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -639,13 +639,14 @@ export namespace Docs {
             const viewKeys = ["x", "y", "system"]; // keys that should be addded to the view document even though they don't begin with an "_"
             const { omit: dataProps, extract: viewProps } = OmitKeys(options, viewKeys, "^_");
 
+            dataProps["acl-Override"] = "None";
+            dataProps["acl-Public"] = options["acl-Public"] ? options["acl-Public"] : Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
+
             dataProps.system = viewProps.system;
             dataProps.isPrototype = true;
             dataProps.author = Doc.CurrentUserEmail;
             dataProps.creationDate = new DateField;
             dataProps[`${fieldKey}-lastModified`] = new DateField;
-            dataProps["acl-Override"] = "None";
-            dataProps["acl-Public"] = options["acl-Public"] ? options["acl-Public"] : Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
 
             dataProps[fieldKey] = data;
 
@@ -654,10 +655,12 @@ export namespace Docs {
             dataProps[fieldKey + "-annotations"] = new List<Doc>();
             const dataDoc = Doc.assign(Doc.MakeDelegate(proto, protoId), dataProps, undefined, true);
 
-            viewProps.author = Doc.CurrentUserEmail;
-            viewProps["acl-Override"] = "None";
-            viewProps["acl-Public"] = options["_acl-Public"] ? options["_acl-Public"] : Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
-            const viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewProps, true, true);
+            const viewFirstProps: { [id: string]: any } = {};
+            viewFirstProps["acl-Public"] = options["_acl-Public"] ? options["_acl-Public"] : Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment;
+            viewFirstProps["acl-Override"] = "None";
+            viewFirstProps.author = Doc.CurrentUserEmail;
+            const viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewFirstProps, true, true);
+            Doc.assign(viewDoc, viewProps, true, true);
             ![DocumentType.LINK, DocumentType.MARKER, DocumentType.LABEL].includes(viewDoc.type as any) && DocUtils.MakeLinkToActiveAudio(() => viewDoc);
 
             !Doc.IsSystem(dataDoc) && ![DocumentType.MARKER, DocumentType.KVP, DocumentType.LINK, DocumentType.LINKANCHOR].includes(proto.type as any) &&
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 436237d6c..083530ce7 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1236,9 +1236,6 @@ ScriptingGlobals.add(async function removeDashboard(dashboard: Doc) {
     "Remove Dashboard from Dashboards");
 ScriptingGlobals.add(function addToDashboards(dashboard: Doc) {
     const dashboardAlias = Doc.MakeAlias(dashboard);
-    dashboardAlias.data = new List<Doc>(DocListCast(dashboard.data).map(tabFolder => Doc.MakeAlias(tabFolder)));
-    DocListCast(dashboardAlias.data).forEach(doc => doc.dashboard = dashboardAlias);
-    DocListCast(dashboardAlias.data)[1].data = ComputedField.MakeFunction(`dynamicOffScreenDocs(self.dashboard)`) as any;
     Doc.AddDocToList(CurrentUserUtils.MyDashboards, "data", dashboardAlias);
     CurrentUserUtils.openDashboard(Doc.UserDoc(), dashboardAlias);
 },
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 1d65256a6..c60434d95 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -109,27 +109,14 @@ export class CollectionDockingView extends CollectionSubView() {
         if (instance) {
             const docList = DocListCast(instance.props.Document[DataSym].data);
             // adds the doc of the newly created tab to the data-all field if it doesn't already include that doc or one of its aliases
-            !docList.includes(document) && !docList.includes(document.aliasOf as Doc) && Doc.AddDocToList(instance.props.Document[DataSym], "data", document);
-            // adds an alias of the doc to the data-all field of the layoutdocs of the aliases
-            DocListCast(instance.props.Document.aliases).forEach(alias => {
-                const aliasDocList = DocListCast(alias.data);
-                // if aliasDocList contains the alias, don't do anything
-                // otherwise add the original or an alias depending on whether the doc you're looking at is the current doc or a different alias
-                !DocListCast(document.aliases).some(a => aliasDocList.includes(a)) && Doc.AddDocToList(alias, "data", document);//alias !== instance.props.Document ? Doc.MakeAlias(document) : document);
-            });
+            !docList.includes(document) && !docList.includes(document.aliasOf as Doc) && Doc.AddDocToList(instance.props.Document, "data", document);
         }
     }
     removeFromTabDocList = (document: Doc) => {
         const instance = CollectionDockingView.Instance;
         if (instance) {
             // adds the doc of the newly created tab to the data-all field if it doesn't already include that doc or one of its aliases
-            Doc.RemoveDocFromList(instance.props.Document[DataSym], "data", document);
-            // adds an alias of the doc to the data-all field of the layoutdocs of the aliases
-            DocListCast(instance.props.Document.aliases).forEach(alias => {
-                // if aliasDocList contains the alias, don't do anything
-                // otherwise add the original or an alias depending on whether the doc you're looking at is the current doc or a different alias
-                Doc.RemoveDocFromList(alias, "data", document);//alias !== instance.props.Document ? Doc.MakeAlias(document) : document);
-            });
+            Doc.RemoveDocFromList(instance.props.Document, "data", document);
             document.type !== DocumentType.KVP && Doc.AddDocToList(CurrentUserUtils.MyHeaderBarDoc, "data", document);
         }
     }
diff --git a/src/client/views/global/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss
index 520ac9357..a14634bdc 100644
--- a/src/client/views/global/globalCssVariables.scss
+++ b/src/client/views/global/globalCssVariables.scss
@@ -10,7 +10,7 @@ $black: #000000;
 $light-blue: #bdddf5;
 $light-blue-transparent: #bdddf590;
 $medium-blue: #4476f7;
-$medium-blue-alt: #4476f73d;
+$medium-blue-alt: #0047ff54;
 $pink: #e0217d;
 $yellow: #f5d747;
 
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 194b3ba27..b0a45091e 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -821,6 +821,7 @@ export namespace Doc {
             delegate[Initializing] = true;
             delegate.proto = doc;
             delegate.author = Doc.CurrentUserEmail;
+            Object.keys(doc).filter(key => key.startsWith("acl")).forEach(key => delegate[key] = doc[key]);
             if (!Doc.IsSystem(doc)) Doc.AddDocToList(doc[DataSym], "aliases", delegate);
             title && (delegate.title = title);
             delegate[Initializing] = false;
diff --git a/src/fields/util.ts b/src/fields/util.ts
index ef5ac79b8..d1e565774 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -138,6 +138,7 @@ export function denormalizeEmail(email: string) {
  * Copies parent's acl fields to the child
  */
 export function inheritParentAcls(parent: Doc, child: Doc) {
+    return;
     const dataDoc = parent[DataSym];
     for (const key of Object.keys(dataDoc)) {
         // if the default acl mode is private, then don't inherit the acl-Public permission, but set it to private.
@@ -177,7 +178,7 @@ const getEffectiveAclCache = computedFn(function (target: any, user?: string) {
 export function GetEffectiveAcl(target: any, user?: string): symbol {
     if (!target) return AclPrivate;
     if (target[UpdatingFromServer]) return AclAdmin;
-    // authored documents are private until an ACL is set.  this also fixes notes that flicker on and off when a remote types to create a private note into a shared collection.
+    // authored documents are private until an ACL is set.
     if (!target[AclSym] && target.author && target.author !== Doc.CurrentUserEmail) return AclPrivate;
     return getEffectiveAclCache(target, user);// all changes received from the server must be processed as Admin.  return this directly so that the acls aren't cached (UpdatingFromServer is not observable)
 }
-- 
cgit v1.2.3-70-g09d2


From ddd38f923180efd0dc4f53a1c3caad4a1f9ed26f Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 26 May 2022 17:40:54 -0400
Subject: removed more code relating to old version of dashboards with on and
 off screen tab lists.  fixed schema headers to not iconify when typing Enter
 in header field name.

---
 .../views/collections/CollectionDockingView.tsx    | 47 +---------------------
 src/client/views/collections/TabDocView.tsx        |  1 -
 .../collectionSchema/CollectionSchemaHeaders.tsx   |  5 ++-
 3 files changed, 6 insertions(+), 47 deletions(-)

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

diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index c60434d95..509da18cb 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -92,8 +92,6 @@ export class CollectionDockingView extends CollectionSubView() {
                     this.setupGoldenLayout(); // restore golden layout to where it was before the drag (this is a no-op when using StartOtherDrag because the proxy dragged item was never in the golden layout)
                 }
                 DragManager.CompleteWindowDrag = undefined;
-            } else {
-                DragManager.DocDragData?.droppedDocuments.forEach(doc => this.addToTabDocList(doc));
             }
             finishDrag?.(aborted);
         };
@@ -104,30 +102,12 @@ export class CollectionDockingView extends CollectionSubView() {
         this.stateChanged();
     }
 
-    addToTabDocList = (document: Doc) => {
-        const instance = CollectionDockingView.Instance;
-        if (instance) {
-            const docList = DocListCast(instance.props.Document[DataSym].data);
-            // adds the doc of the newly created tab to the data-all field if it doesn't already include that doc or one of its aliases
-            !docList.includes(document) && !docList.includes(document.aliasOf as Doc) && Doc.AddDocToList(instance.props.Document, "data", document);
-        }
-    }
-    removeFromTabDocList = (document: Doc) => {
-        const instance = CollectionDockingView.Instance;
-        if (instance) {
-            // adds the doc of the newly created tab to the data-all field if it doesn't already include that doc or one of its aliases
-            Doc.RemoveDocFromList(instance.props.Document, "data", document);
-            document.type !== DocumentType.KVP && Doc.AddDocToList(CurrentUserUtils.MyHeaderBarDoc, "data", document);
-        }
-    }
-
     @undoBatch
     public static CloseSplit(document: Opt<Doc>, panelName?: string): boolean {
         const tab = Array.from(CollectionDockingView.Instance.tabMap.keys()).find((tab) => panelName ? tab.contentItem.config.props.panelName === panelName : tab.DashDoc === document);
         if (tab) {
             const j = tab.header.parent.contentItems.indexOf(tab.contentItem);
             if (j !== -1) {
-                CollectionDockingView.Instance.removeFromTabDocList(tab.dashDoc as Doc);
                 tab.header.parent.contentItems[j].remove();
                 return CollectionDockingView.Instance.layoutChanged();
             }
@@ -206,9 +186,6 @@ export class CollectionDockingView extends CollectionSubView() {
         }
         const instance = CollectionDockingView.Instance;
         if (!instance) return false;
-        else {
-            instance.addToTabDocList(document);
-        }
         const docContentConfig = CollectionDockingView.makeDocumentConfig(document, panelName);
 
         if (!pullSide && stack) {
@@ -434,29 +411,10 @@ export class CollectionDockingView extends CollectionSubView() {
         const matches = json.match(/\"documentId\":\"[a-z0-9-]+\"/g);
         const docids = matches?.map(m => m.replace("\"documentId\":\"", "").replace("\"", ""));
         const docs = !docids ? [] : docids.map(id => DocServer.GetCachedRefField(id)).filter(f => f).map(f => f as Doc);
-        const changesMade = this.props.Document.dockingConfig !== json;
+        const changesMade = this.props.Document.dockcingConfig !== json;
         if (changesMade && !this._flush) {
             this.props.Document.dockingConfig = json;
-            setTimeout(async () => {
-                const sublists = await DocListCastAsync(this.props.Document[this.props.fieldKey]);
-                const tabs = sublists && Cast(sublists[0], Doc, null);
-                // const other = sublists && Cast(sublists[1], Doc, null);
-                const tabdocs = await DocListCastAsync(tabs?.data);
-                // const otherdocs = await DocListCastAsync(other?.data);
-                if (tabs) {
-                    tabs.data = new List<Doc>(docs);
-                    // DocListCast(tabs.aliases).forEach(tab => tab !== tabs && (tab.data = new List<Doc>(docs)));
-                }
-                // const otherSet = new Set<Doc>();
-                // otherdocs?.filter(doc => !docs.includes(doc)).forEach(doc => otherSet.add(doc));
-                // tabdocs?.filter(doc => !docs.includes(doc) && doc.type !== DocumentType.KVP).forEach(doc => otherSet.add(doc));
-                // const vals = Array.from(otherSet.values()).filter(val => val instanceof Doc).map(d => d).filter(d => d.type !== DocumentType.KVP);
-                // this.props.Document[DataSym][this.props.fieldKey + "-all"] = new List<Doc>([...docs, ...vals]);
-                // if (other) {
-                //     other.data = new List<Doc>(vals);
-                //     // DocListCast(other.aliases).forEach(tab => tab !== other && (tab.data = new List<Doc>(vals)));
-                // }
-            }, 0);
+            this.props.Document.data = new List<Doc>(docs);
         }
         return changesMade;
     }
@@ -490,7 +448,6 @@ export class CollectionDockingView extends CollectionSubView() {
                 //if (confirm('really close this?')) {
                 if (!stack.parent.parent.isRoot || stack.parent.contentItems.length > 1) {
                     stack.remove();
-                    stack.contentItems.forEach((contentItem: any) => CollectionDockingView.Instance.removeFromTabDocList(contentItem.tab.DashDoc));
                 } else {
                     alert('cant delete the last stack');
                 }
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index a2ba504dc..2b78b20ea 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -180,7 +180,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             tab.closeElement.off('click') //unbind the current click handler
                 .click(function () {
                     Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
-                    CollectionDockingView.Instance?.removeFromTabDocList(doc);
                     SelectionManager.DeselectAll();
                     UndoManager.RunInBatch(() => tab.contentItem.remove(), "delete tab");
                 });
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx
index dc35b5749..0875c80b3 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaHeaders.tsx
@@ -278,6 +278,7 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
     @undoBatch
     onKeyDown = (e: React.KeyboardEvent): void => {
         if (e.key === "Enter") {
+            e.stopPropagation();
             if (this._searchTerm.includes(":")) {
                 const colpos = this._searchTerm.indexOf(":");
                 const temp = this._searchTerm.slice(colpos + 1, this._searchTerm.length);
@@ -490,7 +491,9 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
 
                 <div className="keys-dropdown" style={{ zIndex: 1, width: this.props.width, maxWidth: this.props.width }}>
                     <input className="keys-search" style={{ width: "100%" }}
-                        ref={this._inputRef} type="text" value={this._searchTerm} placeholder="Column key" onKeyDown={this.onKeyDown}
+                        ref={this._inputRef} type="text"
+                        value={this._searchTerm} placeholder="Column key"
+                        onKeyDown={this.onKeyDown}
                         onChange={e => this.onChange(e.target.value)}
                         onClick={(e) => { e.stopPropagation(); this._inputRef.current?.focus(); }}
                         onFocus={this.onFocus} ></input>
-- 
cgit v1.2.3-70-g09d2

