From f8840672a7bcb3f337d8e50098f374a1b2d441ce Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 8 Jun 2022 01:17:24 -0400
Subject: added ability to make thumbnails of dashboards. started to cleanup
 dockingView/goldenlayout undo event handling.  cleaned up tab doc list in
 docking view.  made titles editable again in treeview.  fixed overlay view to
 work with image docs etc by setting top/left in css

---
 .../views/collections/CollectionDockingView.tsx     | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 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 de2106e4a..5af72b7d1 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -26,6 +26,7 @@ import { CollectionSubView, SubCollectionViewProps } from "./CollectionSubView";
 import { CollectionViewType } from './CollectionView';
 import { TabDocView } from './TabDocView';
 import React = require("react");
+import { SelectionManager } from '../../util/SelectionManager';
 const _global = (window /* browser */ || global /* node */) as any;
 
 @observer
@@ -50,9 +51,8 @@ export class CollectionDockingView extends CollectionSubView() {
     public _flush: UndoManager.Batch | undefined;
     private _ignoreStateChange = "";
     public tabMap: Set<any> = new Set();
-    public get initialized() { return this._goldenLayout !== null; }
     public get HasFullScreen() { return this._goldenLayout._maximisedItem !== null; }
-    @observable private _goldenLayout: any = null;
+    private _goldenLayout: any = null;
 
     constructor(props: SubCollectionViewProps) {
         super(props);
@@ -118,6 +118,7 @@ export class CollectionDockingView extends CollectionSubView() {
 
     @undoBatch
     public static OpenFullScreen(doc: Doc) {
+        SelectionManager.DeselectAll();
         const instance = CollectionDockingView.Instance;
         if (doc._viewType === CollectionViewType.Docking && doc.layoutKey === "layout") {
             return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
@@ -271,7 +272,7 @@ export class CollectionDockingView extends CollectionSubView() {
         return true;
     }
 
-    async setupGoldenLayout() {
+    setupGoldenLayout = async () => {
         const config = StrCast(this.props.Document.dockingConfig);
         if (config) {
             const matches = config.match(/\"documentId\":\"[a-z0-9-]+\"/g);
@@ -291,7 +292,7 @@ export class CollectionDockingView extends CollectionSubView() {
             }
             this.tabMap.clear();
             this._goldenLayout?.destroy();
-            runInAction(() => this._goldenLayout = new GoldenLayout(JSON.parse(config)));
+            this._goldenLayout = new GoldenLayout(JSON.parse(config));
             this._goldenLayout.on('tabCreated', this.tabCreated);
             this._goldenLayout.on('tabDestroyed', this.tabDestroyed);
             this._goldenLayout.on('stackCreated', this.stackCreated);
@@ -322,7 +323,7 @@ export class CollectionDockingView extends CollectionSubView() {
                     }
                     this._ignoreStateChange = "";
                 });
-            setTimeout(() => this.setupGoldenLayout(), 0);
+            setTimeout(this.setupGoldenLayout);
             //window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window
         }
     }
@@ -413,19 +414,25 @@ export class CollectionDockingView extends CollectionSubView() {
         const docs = !docids ? [] : docids.map(id => DocServer.GetCachedRefField(id)).filter(f => f).map(f => f as Doc);
         const changesMade = this.props.Document.dockcingConfig !== json;
         if (changesMade && !this._flush) {
-            this.props.Document.dockingConfig = json;
-            this.props.Document.data = new List<Doc>(docs);
+            UndoManager.RunInBatch(() => {
+                this.props.Document.dockingConfig = json;
+                this.props.Document.data = new List<Doc>(docs);
+            }, "state changed");
         }
         return changesMade;
     }
 
     tabDestroyed = (tab: any) => {
+        const dview = CollectionDockingView.Instance.props.Document;
+        const fieldKey = CollectionDockingView.Instance.props.fieldKey;
+        Doc.RemoveDocFromList(dview, fieldKey, tab.DashDoc);
         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) => {
+        this.tabMap.add(tab);
         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)
     }
 
-- 
cgit v1.2.3-70-g09d2


From 7ab50d37d38a91d564cf3150be35a68d11bdcffe Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 8 Jun 2022 01:45:05 -0400
Subject: undo/redo fixes for docking views (maximizing, closing stacks).
 making maximised tabs persist across refreshes.

---
 src/client/views/collections/CollectionDockingView.tsx | 12 ++++--------
 1 file changed, 4 insertions(+), 8 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 5af72b7d1..745565ff5 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -298,13 +298,6 @@ export class CollectionDockingView extends CollectionSubView() {
             this._goldenLayout.on('stackCreated', this.stackCreated);
             this._goldenLayout.registerComponent('DocumentFrameRenderer', TabDocView);
             this._goldenLayout.container = this._containerRef.current;
-            if (this._goldenLayout.config.maximisedItemId === '__glMaximised') {
-                try {
-                    this._goldenLayout.config.root.getItemsById(this._goldenLayout.config.maximisedItemId)[0].toggleMaximise();
-                } catch (e) {
-                    this._goldenLayout.config.maximisedItemId = null;
-                }
-            }
             this._goldenLayout.init();
             this._goldenLayout.root.layoutManager.on('itemDropped', this.tabItemDropped);
             this._goldenLayout.root.layoutManager.on('dragStart', this.tabDragStart);
@@ -369,7 +362,7 @@ export class CollectionDockingView extends CollectionSubView() {
             const htmlTarget = e.target as HTMLElement;
             window.addEventListener("mouseup", this.onPointerUp);
             if (!htmlTarget.closest("*.lm_content") && (htmlTarget.closest("*.lm_tab") || htmlTarget.closest("*.lm_stack"))) {
-                if (htmlTarget.className !== "lm_close_tab") {
+                if (!htmlTarget.className.includes("lm_close") && !htmlTarget.className.includes("lm_maximise")) {
                     this._flush = UndoManager.StartBatch("golden layout edit");
                 }
             }
@@ -459,6 +452,9 @@ export class CollectionDockingView extends CollectionSubView() {
                     alert('cant delete the last stack');
                 }
             }));
+
+        stack.header?.controlsContainer.find('.lm_maximise') //get the close icon
+            .click(() => setTimeout(this.stateChanged));
         stack.header?.controlsContainer.find('.lm_popout') //get the popout icon
             .off('click') //unbind the current click handler
             .click(action(() => {
-- 
cgit v1.2.3-70-g09d2


From 5157f0c500b01a635c373cc661a2588ef7506d79 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 8 Jun 2022 12:44:36 -0400
Subject: added context menu back to tab's via the doc icon.  made docicon
 draggable and clickable. removed collectiondockingviewmenu.

---
 src/client/goldenLayout.js                         |  5 ++-
 .../views/collections/CollectionDockingView.tsx    |  3 +-
 .../collections/CollectionDockingViewMenu.scss     | 34 ---------------
 .../collections/CollectionDockingViewMenu.tsx      | 48 --------------------
 src/client/views/collections/TabDocView.tsx        | 51 +++++++++++-----------
 5 files changed, 31 insertions(+), 110 deletions(-)
 delete mode 100644 src/client/views/collections/CollectionDockingViewMenu.scss
 delete mode 100644 src/client/views/collections/CollectionDockingViewMenu.tsx

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

diff --git a/src/client/goldenLayout.js b/src/client/goldenLayout.js
index 4735f216f..012ee163c 100644
--- a/src/client/goldenLayout.js
+++ b/src/client/goldenLayout.js
@@ -458,8 +458,9 @@
                 if (this._bDragging === true) {
                     this._bDragging = false;
                     this.emit('dragStop', oEvent, this._nOriginalX + this._nX);
-                } else if (oEvent.target) { // make title receive pointer events to allow setting insertion position or selecting texst range
-                    if (oEvent.target.className.includes("lm_title_wrap")) {
+                } else  { // make title receive pointer events to allow setting insertion position or selecting texst range
+                    const classname = typeof oEvent.target?.className === "string" ? oEvent.target.className : "";
+                    if (classname.includes("lm_title_wrap")) {
                         oEvent.target.children[0].style.pointerEvents = "all";
                         oEvent.target.children[0].focus();
                     }
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 745565ff5..476ffaf81 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -362,7 +362,8 @@ export class CollectionDockingView extends CollectionSubView() {
             const htmlTarget = e.target as HTMLElement;
             window.addEventListener("mouseup", this.onPointerUp);
             if (!htmlTarget.closest("*.lm_content") && (htmlTarget.closest("*.lm_tab") || htmlTarget.closest("*.lm_stack"))) {
-                if (!htmlTarget.className.includes("lm_close") && !htmlTarget.className.includes("lm_maximise")) {
+                const className = typeof htmlTarget.className === "string" ? htmlTarget.className : "";
+                if (!className.includes("lm_close") && !className.includes("lm_maximise")) {
                     this._flush = UndoManager.StartBatch("golden layout edit");
                 }
             }
diff --git a/src/client/views/collections/CollectionDockingViewMenu.scss b/src/client/views/collections/CollectionDockingViewMenu.scss
deleted file mode 100644
index 4157f0f7e..000000000
--- a/src/client/views/collections/CollectionDockingViewMenu.scss
+++ /dev/null
@@ -1,34 +0,0 @@
-
-.dockingViewButtonSelector {
-    div {
-        overflow: visible !important;
-    }
-
-    display: inline-block;
-    width:100%;
-    height:100%;
-}
-.dockingViewButtonSelector-flyout {
-    position: relative;
-    z-index: 9999;
-    background-color: #eeeeee;
-    box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
-    color: black;
-
-    padding: 10px;
-    border-radius: 3px;
-    display: inline-block;
-    height: 100%;
-    width: 100%;
-    border-radius: 3px;
-
-    hr {
-        height: 1px;
-        margin: 0px;
-        background-color: gray;
-        border-top: 0px;
-        border-bottom: 0px;
-        border-right: 0px;
-        border-left: 0px;
-    }
-}
\ No newline at end of file
diff --git a/src/client/views/collections/CollectionDockingViewMenu.tsx b/src/client/views/collections/CollectionDockingViewMenu.tsx
deleted file mode 100644
index 1cab293a8..000000000
--- a/src/client/views/collections/CollectionDockingViewMenu.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Tooltip } from "@material-ui/core";
-import { action, computed, observable } from "mobx";
-import { observer } from "mobx-react";
-import * as React from "react";
-import { DocumentButtonBar } from "../DocumentButtonBar";
-import { DocumentView } from "../nodes/DocumentView";
-const higflyout = require("@hig/flyout");
-export const { anchorPoints } = higflyout;
-export const Flyout = higflyout.default;
-
-@observer
-export class CollectionDockingViewMenu extends React.Component<{ views: () => DocumentView[], Stack: any }> {
-    customStylesheet(styles: any) {
-        return {
-            ...styles,
-            panel: {
-                ...styles.panel,
-                minWidth: "100px"
-            },
-        };
-    }
-    _ref = React.createRef<HTMLDivElement>();
-
-    @computed get flyout() {
-        return (
-            <div className="dockingViewButtonSelector-flyout" title=" " ref={this._ref}>
-                <DocumentButtonBar views={this.props.views} stack={this.props.Stack} />
-            </div>
-        );
-    }
-
-    @observable _tooltipOpen: boolean = false;
-    render() {
-        return <Tooltip open={this._tooltipOpen} onClose={action(() => this._tooltipOpen = false)} title={<><div className="dash-tooltip">Tap for toolbar, drag to create alias in another pane</div></>} placement="bottom">
-            <span className="dockingViewButtonSelector"
-                onPointerEnter={action(() => !this._ref.current?.getBoundingClientRect().width && (this._tooltipOpen = true))}
-                onPointerDown={action(e => {
-                    this.props.views()[0]?.select(false);
-                    this._tooltipOpen = false;
-                })} >
-                <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={this.flyout} stylesheet={this.customStylesheet}>
-                    <FontAwesomeIcon icon={"arrows-alt"} size={"sm"} />
-                </Flyout>
-            </span>
-        </Tooltip >;
-    }
-}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 75a8207dd..91c6975ea 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -4,15 +4,15 @@ import { Tooltip } from '@material-ui/core';
 import 'golden-layout/src/css/goldenlayout-base.css';
 import 'golden-layout/src/css/goldenlayout-dark-theme.css';
 import { clamp } from 'lodash';
-import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx";
+import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
 import { observer } from "mobx-react";
 import * as ReactDOM from 'react-dom';
-import { DataSym, Doc, DocListCast, DocListCastAsync, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
+import { DataSym, Doc, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
 import { Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
 import { FieldId } from "../../../fields/RefField";
 import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types";
-import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, Utils } from "../../../Utils";
+import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from "../../../Utils";
 import { DocServer } from "../../DocServer";
 import { DocUtils } from '../../documents/Documents';
 import { DocumentType } from '../../documents/DocumentTypes';
@@ -27,10 +27,10 @@ import { Colors, Shadows } from '../global/globalEnums';
 import { LightboxView } from '../LightboxView';
 import { MainView } from '../MainView';
 import { DocFocusOptions, DocumentView, DocumentViewProps } from "../nodes/DocumentView";
+import { DashFieldView } from '../nodes/formattedText/DashFieldView';
 import { PinProps, PresBox, PresMovement } from '../nodes/trails';
 import { DefaultStyleProvider, StyleProp } from '../StyleProvider';
 import { CollectionDockingView } from './CollectionDockingView';
-import { CollectionDockingViewMenu } from './CollectionDockingViewMenu';
 import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
 import { CollectionView, CollectionViewType } from './CollectionView';
 import "./TabDocView.scss";
@@ -92,14 +92,28 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 Doc.GetProto(doc).title = e.currentTarget.value;
             }));
 
-            const dragBtnDown = (e: React.PointerEvent) => {
-                setupMoveUpEvents(this, e, e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY), returnFalse, emptyFunction);
-            };
-
-
             if (tab.element[0].children[1].children.length === 1) {
-                iconWrap.className = "lm_iconWrap";
-                iconWrap.id = "lm_iconWrap";
+                iconWrap.className = "lm_iconWrap lm_moreInfo";
+                const dragBtnDown = (e: React.PointerEvent) => {
+                    setupMoveUpEvents(this, e, e => !e.defaultPrevented && DragManager.StartDocumentDrag([iconWrap], new DragManager.DocumentDragData([doc], doc.dropAction as dropActionType), e.clientX, e.clientY), returnFalse, action(e => {
+                        if (this.view) {
+                            SelectionManager.SelectView(this.view, false);
+                            let child = this.view.ContentDiv!.children[0];
+                            while (child.children.length) {
+                                const next = Array.from(child.children).find(c => c.className?.toString().includes("SVGAnimatedString") || typeof (c.className) === "string");
+                                if (next?.className?.toString().includes(DocumentView.ROOT_DIV)) break;
+                                if (next?.className?.toString().includes(DashFieldView.name)) break;
+                                if (next) child = next;
+                                else break;
+                            }
+                            simulateMouseClick(child, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
+                        }
+                        else { this._activated = true;
+                              setTimeout(() =>this.view && SelectionManager.SelectView(this.view, false));
+                        }
+                    }));
+                };
+
                 closeWrap.className = "lm_iconWrap";
                 closeWrap.id = "lm_closeWrap";
                 closeWrap.onclick = (e: MouseEvent) => {
@@ -111,6 +125,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 const closeIcon = <FontAwesomeIcon icon={"times"} />;
                 ReactDOM.render(docIcon, iconWrap);
                 ReactDOM.render(closeIcon, closeWrap);
+                tab.reactComponents = [iconWrap, closeWrap];
                 // tab.element[0].append(closeWrap);
                 tab.element[0].prepend(iconWrap);
                 tab._disposers.layerDisposer = reaction(() => ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }),
@@ -122,7 +137,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                         titleEle.style.backgroundColor = "transparent";
                         iconWrap.style.color = textColor;
                         closeWrap.style.color = textColor;
-                        moreInfoDrag.style.backgroundColor = textColor;
                         tab.element[0].style.background = !layer ? color : "dimgrey";
                     }, { fireImmediately: true });
             }
@@ -155,19 +169,6 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     // toggle.style.textTransform = selected ? "uppercase" : "";
                 }));
 
-            //attach the selection doc buttons menu to the drag handle
-            const stack: HTMLDivElement = tab.contentItem.parent;
-            const header: HTMLDivElement = tab;
-            stack.onscroll = action((e: any) => {
-                console.log('scrolling...');
-            });
-            const moreInfoDrag = document.createElement("div");
-            moreInfoDrag.className = "lm_iconWrap";
-            tab._disposers.buttonDisposer = reaction(() => this.view, view =>
-                view && [ReactDOM.render(<span><CollectionDockingViewMenu views={() => [view]} Stack={stack} /></span>, moreInfoDrag), tab._disposers.buttonDisposer?.()],
-                { fireImmediately: true });
-            // tab.reactComponents = [moreInfoDrag];
-            // tab.element[0].children[3].before(moreInfoDrag);
 
             // highlight the tab when the tab document is brushed in any part of the UI
             tab._disposers.reactionDisposer = reaction(() => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }), ({ title, degree }) => {
-- 
cgit v1.2.3-70-g09d2


From 94975954fbd1ce9b68f6545b16a4eabe4b41cca0 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 8 Jun 2022 14:30:18 -0400
Subject: fixed bug with adding to pres when in miniview mode.

---
 .../views/collections/CollectionDockingView.tsx    | 69 ++++++++++------------
 src/client/views/collections/TabDocView.tsx        |  3 +
 src/client/views/nodes/trails/PresBox.tsx          |  4 +-
 3 files changed, 37 insertions(+), 39 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 476ffaf81..a790a0475 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -172,12 +172,6 @@ export class CollectionDockingView extends CollectionSubView() {
     @undoBatch
     @action
     public static AddSplit(document: Doc, pullSide: string, stack?: any, panelName?: string) {
-        if (document.type === DocumentType.PRES) {
-            const docs = Cast(Cast(Doc.UserDoc().myOverlayDocs, Doc, null).data, listSpec(Doc), []);
-            if (docs.includes(document)) {
-                docs.splice(docs.indexOf(document), 1);
-            }
-        }
         if (document._viewType === CollectionViewType.Docking) return CurrentUserUtils.openDashboard(Doc.UserDoc(), document);
 
         const tab = Array.from(CollectionDockingView.Instance.tabMap).find(tab => tab.DashDoc === document);
@@ -186,6 +180,7 @@ export class CollectionDockingView extends CollectionSubView() {
             return true;
         }
         const instance = CollectionDockingView.Instance;
+        const glayRoot = instance._goldenLayout.root;
         if (!instance) return false;
         const docContentConfig = CollectionDockingView.makeDocumentConfig(document, panelName);
 
@@ -194,29 +189,29 @@ export class CollectionDockingView extends CollectionSubView() {
             stack.setActiveContentItem(stack.contentItems[stack.contentItems.length - 1]);
         } else {
             const newItemStackConfig = { type: 'stack', content: [docContentConfig] };
-            const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
-            if (instance._goldenLayout.root.contentItems.length === 0) { // if no rows / columns
-                instance._goldenLayout.root.addChild(newContentItem);
-            } else if (instance._goldenLayout.root.contentItems[0].isStack) {
-                instance._goldenLayout.root.contentItems[0].addChild(docContentConfig);
+            const newContentItem = glayRoot.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
+            if (glayRoot.contentItems.length === 0) { // if no rows / columns
+                glayRoot.addChild(newContentItem);
+            } else if (glayRoot.contentItems[0].isStack) {
+                glayRoot.contentItems[0].addChild(docContentConfig);
             } else if (
-                instance._goldenLayout.root.contentItems.length === 1 &&
-                instance._goldenLayout.root.contentItems[0].contentItems.length === 1 &&
-                instance._goldenLayout.root.contentItems[0].contentItems[0].contentItems.length === 0) {
-                instance._goldenLayout.root.contentItems[0].contentItems[0].addChild(docContentConfig);
+                glayRoot.contentItems.length === 1 &&
+                glayRoot.contentItems[0].contentItems.length === 1 &&
+                glayRoot.contentItems[0].contentItems[0].contentItems.length === 0) {
+                glayRoot.contentItems[0].contentItems[0].addChild(docContentConfig);
             }
             else if (instance._goldenLayout.root.contentItems[0].isRow) { // if row
                 switch (pullSide) {
                     default:
-                    case "right": instance._goldenLayout.root.contentItems[0].addChild(newContentItem); break;
-                    case "left": instance._goldenLayout.root.contentItems[0].addChild(newContentItem, 0); break;
+                    case "right": glayRoot.contentItems[0].addChild(newContentItem); break;
+                    case "left": glayRoot.contentItems[0].addChild(newContentItem, 0); break;
                     case "top":
                     case "bottom":
                         // if not going in a row layout, must add already existing content into column
-                        const rowlayout = instance._goldenLayout.root.contentItems[0];
+                        const rowlayout = glayRoot.contentItems[0];
                         const newColumn = rowlayout.layoutManager.createContentItem({ type: "column" }, instance._goldenLayout);
 
-                        CollectionDockingView.Instance._goldenLayout.saveScrollTops(rowlayout.element);
+                        instance._goldenLayout.saveScrollTops(rowlayout.element);
                         rowlayout.parent.replaceChild(rowlayout, newColumn);
                         if (pullSide === "top") {
                             newColumn.addChild(rowlayout, undefined, true);
@@ -225,23 +220,23 @@ export class CollectionDockingView extends CollectionSubView() {
                             newColumn.addChild(newContentItem, undefined, true);
                             newColumn.addChild(rowlayout, 0, true);
                         }
-                        CollectionDockingView.Instance._goldenLayout.restoreScrollTops(rowlayout.element);
+                        instance._goldenLayout.restoreScrollTops(rowlayout.element);
 
                         rowlayout.config.height = 50;
                         newContentItem.config.height = 50;
                 }
             } else {// if (instance._goldenLayout.root.contentItems[0].isColumn) { // if column
                 switch (pullSide) {
-                    case "top": instance._goldenLayout.root.contentItems[0].addChild(newContentItem, 0); break;
-                    case "bottom": instance._goldenLayout.root.contentItems[0].addChild(newContentItem); break;
+                    case "top": glayRoot.contentItems[0].addChild(newContentItem, 0); break;
+                    case "bottom": glayRoot.contentItems[0].addChild(newContentItem); break;
                     case "left":
                     case "right":
                     default:
                         // if not going in a row layout, must add already existing content into column
-                        const collayout = instance._goldenLayout.root.contentItems[0];
+                        const collayout = glayRoot.contentItems[0];
                         const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout);
 
-                        CollectionDockingView.Instance._goldenLayout.saveScrollTops(collayout.element);
+                        instance._goldenLayout.saveScrollTops(collayout.element);
                         collayout.parent.replaceChild(collayout, newRow);
                         if (pullSide === "left") {
                             newRow.addChild(collayout, undefined, true);
@@ -250,7 +245,7 @@ export class CollectionDockingView extends CollectionSubView() {
                             newRow.addChild(newContentItem, undefined, true);
                             newRow.addChild(collayout, 0, true);
                         }
-                        CollectionDockingView.Instance._goldenLayout.restoreScrollTops(collayout.element);
+                        instance._goldenLayout.restoreScrollTops(collayout.element);
 
                         collayout.config.width = 50;
                         newContentItem.config.width = 50;
@@ -289,19 +284,19 @@ export class CollectionDockingView extends CollectionSubView() {
                         this._goldenLayout.unbind('stackCreated', this.stackCreated);
                     } catch (e) { }
                 }
+                this.tabMap.clear();
+                this._goldenLayout.destroy();
             }
-            this.tabMap.clear();
-            this._goldenLayout?.destroy();
-            this._goldenLayout = new GoldenLayout(JSON.parse(config));
-            this._goldenLayout.on('tabCreated', this.tabCreated);
-            this._goldenLayout.on('tabDestroyed', this.tabDestroyed);
-            this._goldenLayout.on('stackCreated', this.stackCreated);
-            this._goldenLayout.registerComponent('DocumentFrameRenderer', TabDocView);
-            this._goldenLayout.container = this._containerRef.current;
-            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);
+            const glay = this._goldenLayout = new GoldenLayout(JSON.parse(config));
+            glay.on('tabCreated', this.tabCreated);
+            glay.on('tabDestroyed', this.tabDestroyed);
+            glay.on('stackCreated', this.stackCreated);
+            glay.registerComponent('DocumentFrameRenderer', TabDocView);
+            glay.container = this._containerRef.current;
+            glay.init();
+            glay.root.layoutManager.on('itemDropped', this.tabItemDropped);
+            glay.root.layoutManager.on('dragStart', this.tabDragStart);
+            glay.root.layoutManager.on('activeContentItemChanged', this.stateChanged);
         }
     }
 
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 91c6975ea..34fe572e3 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -35,6 +35,7 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV
 import { CollectionView, CollectionViewType } from './CollectionView';
 import "./TabDocView.scss";
 import React = require("react");
+import { listSpec } from '../../../fields/Schema';
 const _global = (window /* browser */ || global /* node */) as any;
 
 interface TabDocViewProps {
@@ -246,6 +247,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             }
             if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
             if (!Array.from(CollectionDockingView.Instance.tabMap).map(d => d.DashDoc).includes(curPres)) {
+                const docs = Cast(Cast(Doc.UserDoc().myOverlayDocs, Doc, null).data, listSpec(Doc), []);
+                if (docs.includes(curPres)) docs.splice(docs.indexOf(curPres), 1);
                 CollectionDockingView.AddSplit(curPres, "right");
                 setTimeout(() => DocumentManager.Instance.jumpToDocument(doc, false, undefined, []), 100); // keeps the pinned doc in view since the sidebar shifts things
             }
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 1a4be8e0c..591480023 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -403,11 +403,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             // openInTab(targetDoc);
         } else if (curDoc.presMovement === PresMovement.Pan && targetDoc) {
             LightboxView.SetLightboxDoc(undefined);
-            await DocumentManager.Instance.jumpToDocument(targetDoc, false, openInTab, [srcContext], undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection, undefined, true); // documents open in new tab instead of on right
+            await DocumentManager.Instance.jumpToDocument(targetDoc, false, openInTab, srcContext ? [srcContext]:[], undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection, undefined, true); // documents open in new tab instead of on right
         } else if ((curDoc.presMovement === PresMovement.Zoom || curDoc.presMovement === PresMovement.Jump) && targetDoc) {
             LightboxView.SetLightboxDoc(undefined);
             //awaiting jump so that new scale can be found, since jumping is async     
-            await DocumentManager.Instance.jumpToDocument(targetDoc, true, openInTab, [srcContext], undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection, undefined, true, NumCast(curDoc.presZoom)); // documents open in new tab instead of on right    
+            await DocumentManager.Instance.jumpToDocument(targetDoc, true, openInTab, srcContext ? [srcContext]:[], undefined, undefined, undefined, includesDoc || tab ? undefined : resetSelection, undefined, true, NumCast(curDoc.presZoom)); // documents open in new tab instead of on right    
         }
         // After navigating to the document, if it is added as a presPinView then it will
         // adjust the pan and scale to that of the pinView when it was added.
-- 
cgit v1.2.3-70-g09d2


From d1f268c1788f54c62c0779aba224b5b7d30edb01 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 9 Jun 2022 17:13:49 -0400
Subject: changed tab numbering to be relative to dashboard.

---
 src/client/util/CurrentUserUtils.ts                    |  5 ++---
 src/client/views/collections/CollectionDockingView.tsx | 12 ++++++------
 2 files changed, 8 insertions(+), 9 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 2d2dda2b8..3107650d9 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1215,8 +1215,6 @@ export class CurrentUserUtils {
         const presentation = Doc.MakeCopy(userDoc.emptyPresentation as Doc, true);
         const dashboards = await Cast(userDoc.myDashboards, Doc) as Doc;
         const dashboardCount = DocListCast(dashboards.data).length + 1;
-        const emptyPane = Cast(userDoc.emptyPane, Doc, null);
-        emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1;
         const freeformOptions: DocumentOptions = {
             x: 0,
             y: 400,
@@ -1224,7 +1222,7 @@ export class CurrentUserUtils {
             _height: 1000,
             _fitWidth: true,
             _backgroundGridShow: true,
-            title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`,
+            title: `Untitled Tab 1`,
         };
         const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
         const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: `Dashboard ${dashboardCount}` }, id, "row");
@@ -1233,6 +1231,7 @@ export class CurrentUserUtils {
         // switching the tabs from the datadoc to the regular doc
         const dashboardTabs = DocListCast(dashboardDoc[DataSym].data);
         dashboardDoc.data = new List<Doc>(dashboardTabs);
+        dashboardDoc["pane-count"] = 1;
 
         userDoc.activePresentation = presentation;
 
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index a790a0475..87149a4b8 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -428,10 +428,10 @@ export class CollectionDockingView extends CollectionSubView() {
     stackCreated = (stack: any) => {
         stack.header?.element.on('mousedown', (e: any) => {
             if (e.target === stack.header?.element[0] && e.button === 2) {
-                const emptyPane = CurrentUserUtils.EmptyPane;
-                emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1;
+                const dashboard= CurrentUserUtils.ActiveDashboard;
+                dashboard["pane-count"] = NumCast(dashboard["pane-count"]) + 1;
                 const docToAdd = Docs.Create.FreeformDocument([], {
-                    _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _backgroundGridShow: true, _fitWidth: true, title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`,
+                    _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _backgroundGridShow: true, _fitWidth: true, title: `Untitled Tab ${NumCast(dashboard["pane-count"])}`,
                 });
                 this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd);
                 CollectionDockingView.AddSplit(docToAdd, "", stack);
@@ -455,10 +455,10 @@ export class CollectionDockingView extends CollectionSubView() {
             .off('click') //unbind the current click handler
             .click(action(() => {
                 // stack.config.fixed = !stack.config.fixed;  // force the stack to have a fixed size
-                const emptyPane = CurrentUserUtils.EmptyPane;
-                emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1;
+                const dashboard = CurrentUserUtils.ActiveDashboard;
+                dashboard["pane-count"] = NumCast(dashboard["pane-count"]) + 1;
                 const docToAdd = Docs.Create.FreeformDocument([], {
-                    _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _fitWidth: true, _backgroundGridShow: true, title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`
+                    _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _fitWidth: true, _backgroundGridShow: true, title: `Untitled Tab ${NumCast(dashboard["pane-count"])}`
                 });
                 this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd);
                 CollectionDockingView.AddSplit(docToAdd, "", stack);
-- 
cgit v1.2.3-70-g09d2


From 1ab1ff51b5b5769079db1922d5013ec4680a1aa1 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 10 Jun 2022 09:10:54 -0400
Subject: fixed closing tabs to move to headerBar

---
 src/client/views/collections/CollectionDockingView.tsx |  2 ++
 src/client/views/collections/TabDocView.tsx            | 12 ++----------
 2 files changed, 4 insertions(+), 10 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 a790a0475..e657bd502 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -412,6 +412,8 @@ export class CollectionDockingView extends CollectionSubView() {
     }
 
     tabDestroyed = (tab: any) => {
+        Doc.AddDocToList(CurrentUserUtils.MyHeaderBarDoc, "data", tab.DashDoc);
+        Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", tab.DashDoc, undefined, true, true);
         const dview = CollectionDockingView.Instance.props.Document;
         const fieldKey = CollectionDockingView.Instance.props.fieldKey;
         Doc.RemoveDocFromList(dview, fieldKey, tab.DashDoc);
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 142013d1a..6c4437aed 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -115,20 +115,12 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                         }
                     }));
                 };
-
-                closeWrap.className = "lm_iconWrap";
-                closeWrap.id = "lm_closeWrap";
-                closeWrap.onclick = (e: MouseEvent) => {
-                    tab.header.parent.contentItem.remove();
-                    Doc.AddDocToList(CurrentUserUtils.MyHeaderBarDoc, "data", tab.DashDoc);
-                    Doc.AddDocToList(CurrentUserUtils.MyRecentlyClosed, "data", tab.DashDoc, undefined, true, true);
-                };
+                
                 const docIcon = <FontAwesomeIcon onPointerDown={dragBtnDown} icon={iconType} />;
-                const closeIcon = <FontAwesomeIcon icon={"times"} />;
+                const closeIcon = <FontAwesomeIcon icon={"eye"} />;
                 ReactDOM.render(docIcon, iconWrap);
                 ReactDOM.render(closeIcon, closeWrap);
                 tab.reactComponents = [iconWrap, closeWrap];
-                // tab.element[0].append(closeWrap);
                 tab.element[0].prepend(iconWrap);
                 tab._disposers.layerDisposer = reaction(() => ({ layer: tab.DashDoc.activeLayer, color: this.tabColor }),
                     ({ layer, color }) => {
-- 
cgit v1.2.3-70-g09d2


From 04fd9f20ccdc204dad5724008b076cbf9ea7b874 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 10 Jun 2022 13:02:49 -0400
Subject: fixed some initialization problems with tabs

---
 src/client/util/History.ts                         |  6 ++--
 .../views/collections/CollectionDockingView.tsx    | 32 ++++++++++++----------
 2 files changed, 22 insertions(+), 16 deletions(-)

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

diff --git a/src/client/util/History.ts b/src/client/util/History.ts
index e6f75a7db..632348306 100644
--- a/src/client/util/History.ts
+++ b/src/client/util/History.ts
@@ -58,8 +58,10 @@ export namespace HistoryUtil {
 
     export function getState(): ParsedUrl {
         const state = copyState(history.state);
-        state.initializers = state.initializers || {};
-        return state;
+        if (state) {
+            state.initializers = state.initializers || {};
+        }
+        return state ?? {initializers:{}};
     }
 
     // export function addHandler(handler: (state: ParsedUrl | null) => void) {
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 4119fb5ba..d2687df17 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -188,10 +188,13 @@ export class CollectionDockingView extends CollectionSubView() {
             stack.addChild(docContentConfig, undefined);
             stack.setActiveContentItem(stack.contentItems[stack.contentItems.length - 1]);
         } else {
-            const newItemStackConfig = { type: 'stack', content: [docContentConfig] };
-            const newContentItem = glayRoot.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
+            const newContentItem = () => {
+                const newItem = glayRoot.layoutManager.createContentItem({ type: 'stack', content: [docContentConfig] }, instance._goldenLayout);
+                newItem.callDownwards('_$init');
+                return newItem;
+            }
             if (glayRoot.contentItems.length === 0) { // if no rows / columns
-                glayRoot.addChild(newContentItem);
+                glayRoot.addChild(newContentItem());
             } else if (glayRoot.contentItems[0].isStack) {
                 glayRoot.contentItems[0].addChild(docContentConfig);
             } else if (
@@ -203,32 +206,33 @@ export class CollectionDockingView extends CollectionSubView() {
             else if (instance._goldenLayout.root.contentItems[0].isRow) { // if row
                 switch (pullSide) {
                     default:
-                    case "right": glayRoot.contentItems[0].addChild(newContentItem); break;
-                    case "left": glayRoot.contentItems[0].addChild(newContentItem, 0); break;
+                    case "right": glayRoot.contentItems[0].addChild(newContentItem()); break;
+                    case "left": glayRoot.contentItems[0].addChild(newContentItem(), 0); break;
                     case "top":
                     case "bottom":
                         // if not going in a row layout, must add already existing content into column
                         const rowlayout = glayRoot.contentItems[0];
                         const newColumn = rowlayout.layoutManager.createContentItem({ type: "column" }, instance._goldenLayout);
 
+                        const newItem = newContentItem();
                         instance._goldenLayout.saveScrollTops(rowlayout.element);
                         rowlayout.parent.replaceChild(rowlayout, newColumn);
                         if (pullSide === "top") {
                             newColumn.addChild(rowlayout, undefined, true);
-                            newColumn.addChild(newContentItem, 0, true);
+                            newColumn.addChild(newItem, 0, true);
                         } else if (pullSide === "bottom") {
-                            newColumn.addChild(newContentItem, undefined, true);
+                            newColumn.addChild(newItem, undefined, true);
                             newColumn.addChild(rowlayout, 0, true);
                         }
                         instance._goldenLayout.restoreScrollTops(rowlayout.element);
 
                         rowlayout.config.height = 50;
-                        newContentItem.config.height = 50;
+                        newItem.config.height = 50;
                 }
             } else {// if (instance._goldenLayout.root.contentItems[0].isColumn) { // if column
                 switch (pullSide) {
-                    case "top": glayRoot.contentItems[0].addChild(newContentItem, 0); break;
-                    case "bottom": glayRoot.contentItems[0].addChild(newContentItem); break;
+                    case "top": glayRoot.contentItems[0].addChild(newContentItem(), 0); break;
+                    case "bottom": glayRoot.contentItems[0].addChild(newContentItem()); break;
                     case "left":
                     case "right":
                     default:
@@ -236,23 +240,23 @@ export class CollectionDockingView extends CollectionSubView() {
                         const collayout = glayRoot.contentItems[0];
                         const newRow = collayout.layoutManager.createContentItem({ type: "row" }, instance._goldenLayout);
 
+                        const newItem = newContentItem();
                         instance._goldenLayout.saveScrollTops(collayout.element);
                         collayout.parent.replaceChild(collayout, newRow);
                         if (pullSide === "left") {
                             newRow.addChild(collayout, undefined, true);
-                            newRow.addChild(newContentItem, 0, true);
+                            newRow.addChild(newItem, 0, true);
                         } else {
-                            newRow.addChild(newContentItem, undefined, true);
+                            newRow.addChild(newItem, undefined, true);
                             newRow.addChild(collayout, 0, true);
                         }
                         instance._goldenLayout.restoreScrollTops(collayout.element);
 
                         collayout.config.width = 50;
-                        newContentItem.config.width = 50;
+                        newItem.config.width = 50;
                 }
             }
             instance._ignoreStateChange = JSON.stringify(instance._goldenLayout.toConfig());
-            newContentItem.callDownwards('_$init');
         }
 
         return instance.layoutChanged();
-- 
cgit v1.2.3-70-g09d2

