From 2e76877dc1c9c5b1c226f5bd0394d17cabfec0b4 Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Mon, 17 May 2021 18:01:44 -0400
Subject: trying dynamic off screen docs

---
 .../views/collections/CollectionDockingView.tsx    | 43 ++++++++++++++--------
 1 file changed, 28 insertions(+), 15 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 388f9a909..819667834 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -4,7 +4,7 @@ import { action, IReactionDisposer, observable, reaction, runInAction } from "mo
 import { observer } from "mobx-react";
 import * as ReactDOM from 'react-dom';
 import * as GoldenLayout from "../../../client/goldenLayout";
-import { Doc, DocListCast, Opt, DocListCastAsync } from "../../../fields/Doc";
+import { Doc, DocListCast, Opt, DocListCastAsync, DataSym } from "../../../fields/Doc";
 import { Id } from '../../../fields/FieldSymbols';
 import { InkTool } from '../../../fields/InkField';
 import { List } from '../../../fields/List';
@@ -24,6 +24,7 @@ import React = require("react");
 import { DocumentType } from '../../documents/DocumentTypes';
 import { listSpec } from '../../../fields/Schema';
 import { LightboxView } from '../LightboxView';
+import { inheritParentAcls } from '../../../fields/util';
 const _global = (window /* browser */ || global /* node */) as any;
 
 @observer
@@ -160,6 +161,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
         }
         const instance = CollectionDockingView.Instance;
         if (!instance) return false;
+        else Doc.AddDocToList(instance.props.Document[DataSym], "data-all", document);
         const docContentConfig = CollectionDockingView.makeDocumentConfig(document, panelName);
 
         if (!pullSide && stack) {
@@ -381,15 +383,22 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
         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 other = sublists && Cast(sublists[1], Doc, null);
             const tabdocs = await DocListCastAsync(tabs?.data);
-            const otherdocs = await DocListCastAsync(other?.data);
-            tabs && (Doc.GetProto(tabs).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);
-            other && (Doc.GetProto(other).data = new List<Doc>(vals));
+            // 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);
     }
 
@@ -399,7 +408,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
         tab.reactComponents?.forEach((ele: any) => ReactDOM.unmountComponentAtNode(ele));
     }
     tabCreated = (tab: any) => {
-        tab.contentItem.element[0]?.firstChild?.firstChild?.InitTab?.(tab);  // have to explicitly initialize tabs that reuse contents from previous abs (ie, when dragging a tab around a new tab is created for the old content)
+        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)
     }
 
     stackCreated = (stack: any) => {
@@ -407,9 +416,11 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
             if (e.target === stack.header?.element[0] && e.button === 2) {
                 const emptyPane = CurrentUserUtils.EmptyPane;
                 emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1;
-                CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([], {
-                    _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _fitWidth: true, title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`
-                }), "", stack);
+                const docToAdd = Docs.Create.FreeformDocument([], {
+                    _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _fitWidth: true, title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`,
+                });
+                this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd);
+                CollectionDockingView.AddSplit(docToAdd, "", stack);
             }
         });
 
@@ -430,9 +441,11 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
                 // 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;
-                CollectionDockingView.AddSplit(Docs.Create.FreeformDocument([], {
+                const docToAdd = Docs.Create.FreeformDocument([], {
                     _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), _fitWidth: true, title: `Untitled Tab ${NumCast(emptyPane["dragFactory-count"])}`
-                }), "", stack);
+                });
+                this.props.Document.isShared && inheritParentAcls(this.props.Document, docToAdd);
+                CollectionDockingView.AddSplit(docToAdd, "", stack);
             }));
     }
 
-- 
cgit v1.2.3-70-g09d2


From 77c16aa9f00a9d1b5e31ddf5a68d56f183f13691 Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Thu, 20 May 2021 12:47:46 -0400
Subject: dashboard sharing, aliases now work? needs more testing

---
 src/client/util/CurrentUserUtils.ts                   | 19 +++++++++++++------
 .../views/collections/CollectionDockingView.tsx       |  6 +++++-
 2 files changed, 18 insertions(+), 7 deletions(-)

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

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index a8327ae93..e143887fa 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1255,12 +1255,20 @@ Scripting.addGlobal(function shareDashboard(dashboard: Doc) {
     SharingManager.Instance.open(undefined, dashboard);
 },
     "opens sharing dialog for Dashboard");
-Scripting.addGlobal(function addToDashboards(dashboard: Doc) {
+Scripting.addGlobal(async function addToDashboards(dashboard: Doc) {
     const dashboardAlias = Doc.MakeAlias(dashboard);
+    const dockingConfig = JSON.parse(StrCast(dashboardAlias.dockingConfig));
+    dockingConfig.content = [];
+    dashboardAlias.dockingConfig = JSON.stringify(dockingConfig);
+
+    const allDocs = await DocListCastAsync(dashboard[DataSym]["data-all"]);
+
+    dashboardAlias["data-all"] = new List<Doc>((allDocs || []).map(doc => Doc.MakeAlias(doc)));
+
     dashboardAlias.data = new List<Doc>(DocListCast(dashboard.data).map(tabFolder => Doc.MakeAlias(tabFolder)));
-    // DocListCast(dashboardAlias.data).forEach(tabFolder => {
-    //     tabFolder.data = new List<Doc>(DocListCast(tabFolder.data).map(tab => Doc.MakeAlias(tab)));
-    // });
+    DocListCast(dashboardAlias.data).forEach(doc => doc.dashboard = dashboardAlias);
+    DocListCast(dashboardAlias.data)[0].data = new List<Doc>();
+    DocListCast(dashboardAlias.data)[1].data = ComputedField.MakeFunction(`dynamicOffScreenDocs(self.dashboard)`) as any;
     Doc.AddDocToList(CurrentUserUtils.MyDashboards, "data", dashboardAlias);
     CurrentUserUtils.openDashboard(Doc.UserDoc(), dashboardAlias);
 },
@@ -1268,13 +1276,12 @@ Scripting.addGlobal(function addToDashboards(dashboard: Doc) {
 
 Scripting.addGlobal(function dynamicOffScreenDocs(dashboard: Doc) {
     if (dashboard[DataSym] instanceof Doc) {
-        const allDocs = DocListCast(dashboard[DataSym]["data-all"]);
+        const allDocs = DocListCast(dashboard["data-all"]);
         console.log(allDocs);
         const onScreenTab = DocListCast(dashboard.data)[0];
         const onScreenDocs = DocListCast(onScreenTab.data);
         return new List<Doc>(allDocs.reduce((result: Doc[], doc) => {
             !onScreenDocs.includes(doc) && (result.push(doc));
-            // console.log(doc);
             return result;
         }, []));
     }
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 819667834..235fe8950 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -161,7 +161,11 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
         }
         const instance = CollectionDockingView.Instance;
         if (!instance) return false;
-        else Doc.AddDocToList(instance.props.Document[DataSym], "data-all", document);
+        else {
+            const docList = DocListCast(instance.props.Document[DataSym]["data-all"]);
+            !docList.includes(document) && !docList.includes(document.aliasOf as Doc) && Doc.AddDocToList(instance.props.Document[DataSym], "data-all", document);
+            DocListCast(instance.props.Document[DataSym]["aliases"]).forEach(alias => !alias.aliasOf && alias !== instance.props.Document && Doc.AddDocToList(alias, "data-all", Doc.MakeAlias(document)));
+        }
         const docContentConfig = CollectionDockingView.makeDocumentConfig(document, panelName);
 
         if (!pullSide && stack) {
-- 
cgit v1.2.3-70-g09d2


From b85e7819ae46558a659cac73817be0b812d6abbe Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Mon, 31 May 2021 20:18:19 -0400
Subject: sharing dashboard works? pending fixing remnant on screen tabs

---
 src/client/documents/Documents.ts                  | 17 +++---------
 src/client/util/CurrentUserUtils.ts                | 30 +++++++++++++++++++---
 .../views/collections/CollectionDockingView.tsx    |  9 ++++++-
 3 files changed, 38 insertions(+), 18 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 6fb6f70b3..70541b559 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -648,9 +648,8 @@ export namespace Docs {
          * constructor just generates a new GUID. This is currently used
          * only when creating a DockDocument from the current user's already existing
          * main document.
-         * @param layoutData whether the fieldKey field on the layout doc should store the data or the data doc
          */
-        function InstanceFromProto(proto: Doc, data: Field | undefined, options: DocumentOptions, delegId?: string, fieldKey: string = "data", protoId?: string, layoutData?: boolean) {
+        function InstanceFromProto(proto: Doc, data: Field | undefined, options: DocumentOptions, delegId?: string, fieldKey: string = "data", protoId?: string) {
             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, "^_");
 
@@ -662,16 +661,8 @@ export namespace Docs {
             dataProps["acl-Override"] = "None";
             dataProps["acl-Public"] = Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Add;
 
-            if (layoutData) {
-                viewProps[fieldKey] = data;
-                const list = new List<Doc>();
-                console.log(DocListCast(data));
-                DocListCast(data).forEach(doc => {
-                    list.push(...DocListCast(doc.data));
-                });
-                dataProps[fieldKey + "-all"] = list;
-            }
-            else dataProps[fieldKey] = data;
+            dataProps[fieldKey] = data;
+
             // so that the list of annotations is already initialised, prevents issues in addonly.
             // without this, if a doc has no annotations but the user has AddOnly privileges, they won't be able to add an annotation because they would have needed to create the field's list which they don't have permissions to do.
             dataProps[fieldKey + "-annotations"] = new List<Doc>();
@@ -902,7 +893,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 });
             const all = TreeDocument([], { title: "Off-Screen Tabs", childDontRegisterViews: true, freezeChildren: "add", treeViewExpandedViewLock: true, treeViewExpandedView: "data", system: true });
-            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List([tabs, all]), { freezeChildren: "remove|add", treeViewExpandedViewLock: true, treeViewExpandedView: "data", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id, undefined, undefined, true);
+            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List([tabs, all]), { freezeChildren: "remove|add", treeViewExpandedViewLock: true, treeViewExpandedView: "data", ...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 e143887fa..90a2378fe 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1187,6 +1187,22 @@ export class CurrentUserUtils {
         const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
         const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: `Dashboard ${dashboardCount}` }, id, "row"); // add isFolder:true here?
         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;
 
@@ -1257,14 +1273,18 @@ Scripting.addGlobal(function shareDashboard(dashboard: Doc) {
     "opens sharing dialog for Dashboard");
 Scripting.addGlobal(async function addToDashboards(dashboard: Doc) {
     const dashboardAlias = Doc.MakeAlias(dashboard);
-    const dockingConfig = JSON.parse(StrCast(dashboardAlias.dockingConfig));
-    dockingConfig.content = [];
-    dashboardAlias.dockingConfig = JSON.stringify(dockingConfig);
 
     const allDocs = await DocListCastAsync(dashboard[DataSym]["data-all"]);
 
+    // moves the data-all field from the datadoc to the layoutdoc, necessary for off screen docs tab to function properly
+    dashboard["data-all"] = new List<Doc>(allDocs);
     dashboardAlias["data-all"] = new List<Doc>((allDocs || []).map(doc => Doc.MakeAlias(doc)));
 
+    const dockingConfig = JSON.parse(StrCast(dashboardAlias.dockingConfig));
+    dockingConfig.content = [];
+    dashboardAlias.dockingConfig = JSON.stringify(dockingConfig);
+
+
     dashboardAlias.data = new List<Doc>(DocListCast(dashboard.data).map(tabFolder => Doc.MakeAlias(tabFolder)));
     DocListCast(dashboardAlias.data).forEach(doc => doc.dashboard = dashboardAlias);
     DocListCast(dashboardAlias.data)[0].data = new List<Doc>();
@@ -1274,10 +1294,12 @@ Scripting.addGlobal(async 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.
+ */
 Scripting.addGlobal(function dynamicOffScreenDocs(dashboard: Doc) {
     if (dashboard[DataSym] instanceof Doc) {
         const allDocs = DocListCast(dashboard["data-all"]);
-        console.log(allDocs);
         const onScreenTab = DocListCast(dashboard.data)[0];
         const onScreenDocs = DocListCast(onScreenTab.data);
         return new List<Doc>(allDocs.reduce((result: Doc[], doc) => {
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 235fe8950..2e44b65e6 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -163,8 +163,15 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
         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);
-            DocListCast(instance.props.Document[DataSym]["aliases"]).forEach(alias => !alias.aliasOf && alias !== instance.props.Document && Doc.AddDocToList(alias, "data-all", Doc.MakeAlias(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", alias !== instance.props.Document ? Doc.MakeAlias(document) : document);
+            });
         }
         const docContentConfig = CollectionDockingView.makeDocumentConfig(document, panelName);
 
-- 
cgit v1.2.3-70-g09d2

