From 7174328702fe6b350780728db890141f50ceec5b Mon Sep 17 00:00:00 2001
From: anika <anika.ahluwalia@gmail.com>
Date: Thu, 31 Dec 2020 10:29:20 -0600
Subject: last add b efore pull

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

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

diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 93d3be1fc..b5e498503 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -441,7 +441,11 @@ export class TreeView extends React.Component<TreeViewProps> {
 
     @computed get renderBullet() {
         TraceMobx();
-        const iconType = Doc.toIcon(this.doc);
+        const iconType = this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon);
+
+
+        // const footerDecoration = this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.Decoration + ":footer");
+
         const checked = this.onCheckedClick ? (this.doc.treeViewChecked ?? "unchecked") : undefined;
         return <div className={`bullet${this.outlineMode ? "-outline" : ""}`} key={"bullet"}
             title={this.childDocs?.length ? `click to see ${this.childDocs?.length} items` : "view fields"}
-- 
cgit v1.2.3-70-g09d2


From a70a224d40ed511e8278ce01a74fb0a8a012b075 Mon Sep 17 00:00:00 2001
From: anika <anika.ahluwalia@gmail.com>
Date: Thu, 31 Dec 2020 11:32:41 -0600
Subject: small merge fixes

---
 src/client/views/MainView.tsx              |  5 ++--
 src/client/views/StyleProvider.tsx         | 40 ++++++++++++++++++++++++++++++
 src/client/views/collections/TreeView.scss | 21 +++++++++++-----
 src/client/views/collections/TreeView.tsx  |  5 +++-
 4 files changed, 62 insertions(+), 9 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index e43b8baf1..d17b72639 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -44,6 +44,7 @@ import { KeyManager } from './GlobalKeyHandler';
 import { InkStrokeProperties } from './InkStrokeProperties';
 import { LinkMenu } from './linking/LinkMenu';
 import "./MainView.scss";
+import "./collections/TreeView.scss";
 import { AudioBox } from './nodes/AudioBox';
 import { DocumentLinksButton } from './nodes/DocumentLinksButton';
 import { DocumentView, DocumentViewProps } from './nodes/DocumentView';
@@ -58,7 +59,7 @@ import { PDFMenu } from './pdf/PDFMenu';
 import { PreviewCursor } from './PreviewCursor';
 import { PropertiesView } from './PropertiesView';
 import { SearchBox } from './search/SearchBox';
-import { DefaultStyleProvider, StyleProp } from './StyleProvider';
+import { DefaultStyleProvider, DashboardStyleProvider, StyleProp } from './StyleProvider';
 import { FieldViewProps } from './nodes/FieldView';
 const _global = (window /* browser */ || global /* node */) as any;
 
@@ -342,7 +343,7 @@ export class MainView extends React.Component {
                         PanelHeight={this.getContentsHeight}
                         renderDepth={0}
                         focus={emptyFunction}
-                        styleProvider={this._sidebarContent.proto === Doc.UserDoc().myDashboards ? this.DashboardStyleProvider : DefaultStyleProvider}
+                        styleProvider={this._sidebarContent.title === "My Dashboards" ? DashboardStyleProvider : DefaultStyleProvider}
                         parentActive={returnTrue}
                         whenActiveChanged={emptyFunction}
                         bringToFront={emptyFunction}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index a6e3516ed..c9eedb85d 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -15,6 +15,7 @@ import { MainView } from './MainView';
 import { DocumentViewProps } from "./nodes/DocumentView";
 import { FieldViewProps } from './nodes/FieldView';
 import "./StyleProvider.scss";
+import "./collections/TreeView.scss";
 import React = require("react");
 import Color = require('color');
 
@@ -169,6 +170,45 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps |
     }
 }
 
+
+function toggleHidden(e: React.MouseEvent, doc: Doc) {
+    UndoManager.RunInBatch(() => runInAction(() => {
+        e.stopPropagation();
+        doc.hidden = doc.hidden ? undefined : true;
+    }), "toggleHidden");
+}
+
+function toggleLock(e: React.MouseEvent, doc: Doc) {
+    UndoManager.RunInBatch(() => runInAction(() => {
+        e.stopPropagation();
+        doc.lockedPosition = doc.lockedPosition ? undefined : true;
+    }), "toggleHidden");
+}
+
+/**
+ * add lock and hide button decorations for the "Dashboards" flyout TreeView
+ */
+export function DashboardStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps | DocumentViewProps>, property: string) {
+    switch (property.split(":")[0]) {
+        case StyleProp.Decorations:
+            if (doc) {
+                const hidden = doc.hidden;
+                const locked = doc.lockedPosition;
+                return doc._viewType === CollectionViewType.Docking || (Doc.IsSystem(doc) && Doc.UserDoc().noviceMode) ? (null) :
+                    <>
+                        <div className={`styleProvider-treeView-hide${hidden ? "-active" : ""}`} onClick={(e) => toggleHidden(e, doc)}>
+                            <FontAwesomeIcon icon={hidden ? "eye-slash" : "eye"} size="sm" />
+                        </div>
+                        <div className={`styleProvider-treeView-lock${locked ? "-active" : ""}`} onClick={(e) => toggleLock(e, doc)}>
+                            <FontAwesomeIcon icon={locked ? "lock" : "unlock"} size="sm" />
+                        </div>
+                    </>;
+            }
+        default: return DefaultStyleProvider(doc, props, property);
+
+    }
+}
+
 //
 // a preliminary semantic-"layering/grouping" mechanism for determining interactive properties of documents
 //  currently, the provider tests whether the docuemnt's layer field matches the activeLayer field of the tab.
diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss
index 1208fa07d..2f74a49bb 100644
--- a/src/client/views/collections/TreeView.scss
+++ b/src/client/views/collections/TreeView.scss
@@ -29,7 +29,7 @@
         }
 
         .treeView-checkIcon {
-            left: 3px;
+            left: 3.5px;
             top: 2px;
             position: absolute;
         }
@@ -118,12 +118,18 @@
         margin-left: 0.25rem;
         opacity: 0.75;
 
-        >svg, .styleProvider-treeView-lock, .styleProvider-treeView-hide, .styleProvider-treeView-lock-active, .styleProvider-treeView-hide-active {
+        >svg,
+        .styleProvider-treeView-lock,
+        .styleProvider-treeView-hide,
+        .styleProvider-treeView-lock-active,
+        .styleProvider-treeView-hide-active {
             margin-left: 0.25rem;
-            margin-right: 0.25rem; 
+            margin-right: 0.25rem;
         }
-    
-        >svg, .styleProvider-treeView-lock, .styleProvider-treeView-hide {
+
+        >svg,
+        .styleProvider-treeView-lock,
+        .styleProvider-treeView-hide {
             display: none;
         }
     }
@@ -148,7 +154,10 @@
     }
 
     .right-buttons-container {
-        >svg, .styleProvider-treeView-lock, .styleProvider-treeView-hide {
+
+        >svg,
+        .styleProvider-treeView-lock,
+        .styleProvider-treeView-hide {
             display: inherit;
         }
     }
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 2f9a2f3eb..a297ad708 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -590,7 +590,10 @@ export class TreeView extends React.Component<TreeViewProps> {
                 }} >
                 {view}
             </div >
-            {this.headerElements}
+            <div className={"right-buttons-container"}>
+                {this.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.Decorations)} {/* hide and lock buttons */}
+                {this.headerElements}
+            </div>
         </>;
     }
 
-- 
cgit v1.2.3-70-g09d2


From b98c90c3c59eb5f65a4c7aad7ff8247558a5564c Mon Sep 17 00:00:00 2001
From: anika <anika.ahluwalia@gmail.com>
Date: Thu, 7 Jan 2021 10:33:04 -0600
Subject: last before pull

---
 src/client/views/StyleProvider.tsx        | 2 +-
 src/client/views/collections/TreeView.tsx | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

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

diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index c9eedb85d..607783d51 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -73,7 +73,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps |
     const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity);
 
     switch (property.split(":")[0]) {
-        case StyleProp.TreeViewIcon: return doc && Doc.toIcon(doc);
+        case StyleProp.TreeViewIcon: return doc ? Doc.toIcon(doc) : "question";
         case StyleProp.DocContents: return undefined;
         case StyleProp.WidgetColor: return darkScheme() ? "lightgrey" : "dimgrey";
         case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null));
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index a297ad708..6a0e05215 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -441,14 +441,17 @@ export class TreeView extends React.Component<TreeViewProps> {
 
     @computed get renderBullet() {
         TraceMobx();
+
         const iconType = Doc.toIcon(this.doc);
 
+        // console.log(this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon)); <- always undefined
         //const iconType = this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon);
 
 
         // const footerDecoration = this.titleStyleProvider?.(this.doc, this.props.treeView.props, StyleProp.Decoration + ":footer");
 
         const checked = this.onCheckedClick ? (this.doc.treeViewChecked ?? "unchecked") : undefined;
+
         return <div className={`bullet${this.outlineMode ? "-outline" : ""}`} key={"bullet"}
             title={this.childDocs?.length ? `click to see ${this.childDocs?.length} items` : "view fields"}
             onClick={this.bulletClick}
-- 
cgit v1.2.3-70-g09d2


From 00127a4fccbd00eb3d05699a3a14f52feb7b57db Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Tue, 6 Apr 2021 00:14:21 -0400
Subject: minor cleanup + style across files

---
 src/client/views/DocumentDecorations.tsx            | 10 +++++-----
 src/client/views/PropertiesView.tsx                 |  4 ++--
 src/client/views/StyleProvider.tsx                  |  1 +
 src/client/views/collections/CollectionTreeView.tsx |  2 +-
 src/client/views/collections/TreeView.tsx           |  2 +-
 src/client/views/nodes/FilterBox.tsx                |  7 +++----
 src/client/views/nodes/LinkDocPreview.tsx           |  2 +-
 7 files changed, 14 insertions(+), 14 deletions(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index ce7ff1bbd..e23374cea 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -83,7 +83,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
             UndoManager.RunInBatch(() => titleFieldKey && SelectionManager.Views().forEach(d => {
                 titleFieldKey === "title" && (d.dataDoc["title-custom"] = !this._accumulatedTitle.startsWith("-"));
                 //@ts-ignore
-                Doc.SetInPlace(d.rootDoc, titleFieldKey, +this._accumulatedTitle == this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle, true);
+                Doc.SetInPlace(d.rootDoc, titleFieldKey, +this._accumulatedTitle === this._accumulatedTitle ? +this._accumulatedTitle : this._accumulatedTitle, true);
             }), "title blur");
         }
     }
@@ -376,10 +376,10 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
         this._inkDragDocs.map(oldbds => ({ oldbds, inkPts: Cast(oldbds.doc.data, InkField)?.inkData || [] }))
             .forEach(({ oldbds: { doc, x, y, width, height }, inkPts }) => {
                 Doc.GetProto(doc).data = new InkField(inkPts.map(ipt =>  // (new x — oldx) + newWidth * (oldxpoint /oldWidth)
-                    ({
-                        X: (NumCast(doc.x) - x) + NumCast(doc.width) * ipt.X / width,
-                        Y: (NumCast(doc.y) - y) + NumCast(doc.height) * ipt.Y / height
-                    })));
+                ({
+                    X: (NumCast(doc.x) - x) + NumCast(doc.width) * ipt.X / width,
+                    Y: (NumCast(doc.y) - y) + NumCast(doc.height) * ipt.Y / height
+                })));
                 Doc.SetNativeWidth(doc, undefined);
                 Doc.SetNativeHeight(doc, undefined);
             });
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index df4dd7788..782a0e29e 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -951,7 +951,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 !this.openFilters ? (null) :
                     <div className="propertiesView-filters-content" style={{ height: this.filterDoc.currentFilter[HeightSym]() + 15 }}>
                         <DocumentView
-                            Document={this.filterDoc.currentFilter as Doc}
+                            Document={this.filterDoc.currentFilter}
                             DataDoc={undefined}
                             addDocument={undefined}
                             addDocTab={returnFalse}
@@ -962,7 +962,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                             PanelWidth={() => this.props.width}
                             PanelHeight={this.filterDoc.currentFilter[HeightSym]}
                             renderDepth={0}
-                            scriptContext={this.filterDoc.currentFilter as Doc}
+                            scriptContext={this.filterDoc.currentFilter}
                             focus={emptyFunction}
                             styleProvider={DefaultStyleProvider}
                             isContentActive={returnTrue}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index d1e2fefcb..3853d5888 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -18,6 +18,7 @@ import "./collections/TreeView.scss";
 import "./nodes/FilterBox.scss";
 import React = require("react");
 import Color = require('color');
+import { FieldViewProps } from './nodes/FieldView';
 
 export enum StyleLayers {
     Background = "background"
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index a9e73583d..959864a60 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -59,7 +59,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
     componentWillMount() {
         this._disposers.autoheight = reaction(() => this.rootDoc.autoHeight,
             auto => auto && this.computeHeight(),
-            { fireImmediately: true })
+            { fireImmediately: true });
     }
 
     refList: Set<any> = new Set();
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 2c3a6c0d7..5df33afe0 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -174,7 +174,7 @@ export class TreeView extends React.Component<TreeViewProps> {
 
     componentWillUnmount() {
         this._selDisposer?.();
-        this._treeEle && this.props.unobserveHeight(this._treeEle)
+        this._treeEle && this.props.unobserveHeight(this._treeEle);
         document.removeEventListener("pointermove", this.onDragMove, true);
         document.removeEventListener("pointermove", this.onDragUp, true);
     }
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index ae5b79aec..30d7ed187 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -82,9 +82,8 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
     * @returns the relevant doc according to the value of FilterBox._filterScope i.e. either the Current Dashboard or the Current Collection
     */
     @computed static get targetDoc() {
-        console.log("recomputing");
         if (FilterBox._filterScope === "Current Collection") {
-            return SelectionManager.Views()[0]?.Document.type === "collection" ? SelectionManager.Views()[0].Document : SelectionManager.Views()[0]?.props.ContainingCollectionDoc!;
+            return SelectionManager.Views()[0]?.Document.type === DocumentType.COL ? SelectionManager.Views()[0].Document : SelectionManager.Views()[0]?.props.ContainingCollectionDoc!;
         }
         else return CurrentUserUtils.ActiveDashboard;
     }
@@ -172,10 +171,10 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
     public removeFilter = (filterName: string) => {
         const targetDoc = FilterBox.targetDoc;
         const filterDoc = targetDoc.currentFilter as Doc;
-        const attributes = DocListCast(filterDoc["data"]);
+        const attributes = DocListCast(filterDoc.data);
         const found = attributes.findIndex(doc => doc.title === filterName);
         if (found !== -1) {
-            (filterDoc["data"] as List<Doc>).splice(found, 1);
+            (filterDoc.data as List<Doc>).splice(found, 1);
             const docFilter = Cast(targetDoc._docFilters, listSpec("string"));
             if (docFilter) {
                 let index: number;
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 45e3c8382..b73fb10df 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -26,7 +26,7 @@ interface LinkDocPreviewProps {
 @observer
 export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
     @action public static Clear() { LinkDocPreview.LinkInfo = undefined; }
-    @action public static SetLinkInfo(info?: LinkDocPreviewProps) { LinkDocPreview.LinkInfo != info && (LinkDocPreview.LinkInfo = info); }
+    @action public static SetLinkInfo(info?: LinkDocPreviewProps) { LinkDocPreview.LinkInfo !== info && (LinkDocPreview.LinkInfo = info); }
 
     _infoRef = React.createRef<HTMLDivElement>();
     @observable public static LinkInfo: Opt<LinkDocPreviewProps>;
-- 
cgit v1.2.3-70-g09d2


From e675858cfab46300a543b1013c7f88c8233ed7ad Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 6 Apr 2021 11:09:26 -0400
Subject: added ability to remove filters using inline context menu

---
 .../views/collections/CollectionTreeView.tsx       |  2 +-
 src/client/views/collections/TreeView.tsx          | 12 +++++---
 src/client/views/nodes/DocumentView.tsx            |  5 ++--
 src/client/views/nodes/FilterBox.tsx               | 34 ++++++++--------------
 4 files changed, 24 insertions(+), 29 deletions(-)

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

diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 959864a60..55fe84835 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -101,7 +101,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         const targetDataDoc = this.doc[DataSym];
         const value = DocListCast(targetDataDoc[this.props.fieldKey]);
         const result = value.filter(v => !docs.includes(v));
-        SelectionManager.DeselectAll();
+        if ((doc instanceof Doc ? [doc] : doc).some(doc => SelectionManager.Views().some(dv => Doc.AreProtosEqual(dv.rootDoc, doc)))) SelectionManager.DeselectAll();
         if (result.length !== value.length) {
             const ind = targetDataDoc[this.props.fieldKey].indexOf(doc);
             const prev = ind && targetDataDoc[this.props.fieldKey][ind - 1];
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 5df33afe0..8a5425992 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -21,7 +21,7 @@ import { Transform } from '../../util/Transform';
 import { undoBatch, UndoManager } from '../../util/UndoManager';
 import { EditableView } from "../EditableView";
 import { TREE_BULLET_WIDTH } from '../globalCssVariables.scss';
-import { DocumentView, DocumentViewProps, StyleProviderFunc } from '../nodes/DocumentView';
+import { DocumentView, DocumentViewProps, StyleProviderFunc, DocumentViewInternal } from '../nodes/DocumentView';
 import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
 import { RichTextMenu } from '../nodes/formattedText/RichTextMenu';
 import { KeyValueBox } from '../nodes/KeyValueBox';
@@ -483,17 +483,21 @@ export class TreeView extends React.Component<TreeViewProps> {
     }
 
     @computed get headerElements() {
-        return this.props.treeViewHideHeaderFields() || Doc.IsSystem(this.doc) ? (null)
+        return this.props.treeViewHideHeaderFields() ? (null)
             : <>
                 <FontAwesomeIcon key="bars" icon="bars" size="sm" onClick={e => { this.showContextMenu(e); e.stopPropagation(); }} />
-                {this.doc.treeViewExpandedViewLock ? (null) :
+                {this.doc.treeViewExpandedViewLock || Doc.IsSystem(this.doc) ? (null) :
                     <span className="collectionTreeView-keyHeader" key={this.treeViewExpandedView} onPointerDown={this.expandNextviewType}>
                         {this.treeViewExpandedView}
                     </span>}
             </>;
     }
 
-    showContextMenu = (e: React.MouseEvent) => simulateMouseClick(this._docRef?.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
+    showContextMenu = (e: React.MouseEvent) => {
+        DocumentViewInternal.SelectOnContextsMenu = false;
+        simulateMouseClick(this._docRef?.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
+        DocumentViewInternal.SelectOnContextsMenu = true;
+    }
     contextMenuItems = () => Doc.IsSystem(this.doc) ? [] : this.doc.isFolder ?
         [{ script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" }] :
         this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) ?
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 1c4008a55..703e78470 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -658,7 +658,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
 
         const customScripts = Cast(this.props.Document.contextMenuScripts, listSpec(ScriptField), []);
         Cast(this.props.Document.contextMenuLabels, listSpec("string"), []).forEach((label, i) =>
-            cm.addItem({ description: label, event: () => customScripts[i]?.script.run({ this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: "sticky-note" }));
+            cm.addItem({ description: label, event: () => customScripts[i]?.script.run({ documentView: this, this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: "sticky-note" }));
         this.props.contextMenuItems?.().forEach(item =>
             item.label && cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: "sticky-note" }));
 
@@ -746,8 +746,9 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
 
         if (!this.topMost) e?.stopPropagation(); // DocumentViews should stop propagation of this event
         cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15);
-        !this.props.isSelected(true) && setTimeout(() => SelectionManager.SelectView(this.props.DocumentView(), false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up.  by delaying the selection until hopefully after the pointer up, the context menu will appear.
+        DocumentViewInternal.SelectOnContextsMenu && !this.props.isSelected(true) && setTimeout(() => SelectionManager.SelectView(this.props.DocumentView(), false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up.  by delaying the selection until hopefully after the pointer up, the context menu will appear.
     }
+    public static SelectOnContextsMenu = true;
 
     rootSelected = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false;
     panelHeight = () => this.props.PanelHeight() - this.headerMargin;
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index 30d7ed187..0a010c105 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -167,7 +167,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
         });
         return { strings: Array.from(valueSet.keys()), rtFields };
     }
-
+    removeFilterDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).map(doc => this.removeFilter(StrCast(doc.title))).length ? true : false;
     public removeFilter = (filterName: string) => {
         const targetDoc = FilterBox.targetDoc;
         const filterDoc = targetDoc.currentFilter as Doc;
@@ -190,8 +190,8 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
                 }
             }
         }
+        return true;
     }
-
     /**
      * Responds to clicking the check box in the flyout menu
      */
@@ -199,22 +199,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
         const targetDoc = FilterBox.targetDoc;
         const found = this.activeAttributes.findIndex(doc => doc.title === facetHeader);
         if (found !== -1) {
-            // comment this bit out later once the x works in treeview
-            (this.dataDoc[this.props.fieldKey] as List<Doc>).splice(found, 1);
-            const docFilter = Cast(targetDoc._docFilters, listSpec("string"));
-            if (docFilter) {
-                let index: number;
-                while ((index = docFilter.findIndex(item => item.split(":")[0] === facetHeader)) !== -1) {
-                    docFilter.splice(index, 1);
-                }
-            }
-            const docRangeFilters = Cast(targetDoc._docRangeFilters, listSpec("string"));
-            if (docRangeFilters) {
-                let index: number;
-                while ((index = docRangeFilters.findIndex(item => item.split(":")[0] === facetHeader)) !== -1) {
-                    docRangeFilters.splice(index, 3);
-                }
-            }
+            this.removeFilter(facetHeader);
         } else {
             const allCollectionDocs = DocListCast((targetDoc.data as any)[0].data);
             const facetValues = this.gatherFieldValues(targetDoc, facetHeader);
@@ -232,7 +217,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
             });
             let newFacet: Opt<Doc>;
             if (facetHeader === "text" || facetValues.rtFields / allCollectionDocs.length > 0.1) {
-                newFacet = Docs.Create.TextDocument("", { _width: 100, _height: 25, system: true, _stayInCollection: true, _hideContextMenu: true, treeViewExpandedView: "layout", title: facetHeader, treeViewOpen: true, _forceActive: true, ignoreClick: true });
+                newFacet = Docs.Create.TextDocument("", { _width: 100, _height: 25, system: true, _stayInCollection: true, treeViewExpandedView: "layout", title: facetHeader, treeViewOpen: true, _forceActive: true, ignoreClick: true });
                 Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox
                 newFacet._textBoxPadding = 4;
                 const scriptText = `setDocFilter(this?.target, "${facetHeader}", text, "match")`;
@@ -261,7 +246,11 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
                 newFacet.target = targetDoc;
                 newFacet.data = ComputedField.MakeFunction(`readFacetData(self.target, "${facetHeader}")`);
             }
-            newFacet && Doc.AddDocToList(this.dataDoc, this.props.fieldKey, newFacet);
+            this.props.docViewPath()[0].ComponentView
+            const remove = ScriptField.MakeScript(`documentView.props.removeDocument(self)`, { documentView: "any" });
+            newFacet.contextMenuScripts = new List<ScriptField>([remove!]);
+            newFacet.contextMenuLabels = new List<string>(["Remove"]);
+            Doc.AddDocToList(this.dataDoc, this.props.fieldKey, newFacet);
         }
     }
 
@@ -450,7 +439,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
                     whenChildContentsActiveChanged={returnFalse}
                     treeViewHideTitle={true}
                     focus={returnFalse}
-                    treeViewHideHeaderFields={true}
+                    treeViewHideHeaderFields={false}
                     onCheckedClick={this.scriptField}
                     dontRegisterView={true}
                     styleProvider={this.props.styleProvider}
@@ -458,7 +447,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
                     docViewPath={this.props.docViewPath}
                     scriptContext={this.props.scriptContext}
                     moveDocument={returnFalse}
-                    removeDocument={returnFalse}
+                    removeDocument={this.removeFilterDoc}
                     addDocument={returnFalse} />
             </div>
             <div className="filterBox-bottom">
@@ -519,6 +508,7 @@ Scripting.addGlobal(function readFacetData(layoutDoc: Doc, facetHeader: string)
     const facetValues = Array.from(set).filter(v => v);
 
     let nonNumbers = 0;
+
     facetValues.map(val => Number.isNaN(Number(val)) && nonNumbers++);
     const facetValueDocSet = (nonNumbers / facetValues.length > .1 ? facetValues.sort() : facetValues.sort((n1: string, n2: string) => Number(n1) - Number(n2))).map(facetValue => {
         const doc = new Doc();
-- 
cgit v1.2.3-70-g09d2


From d01fdacae8e96c99a095dd2c97f62144ab81def5 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 6 Apr 2021 13:01:12 -0400
Subject: fix to get text filtering to work.

---
 src/client/views/collections/CollectionTreeView.tsx |  2 +-
 src/client/views/collections/TreeView.tsx           |  2 +-
 src/client/views/nodes/FilterBox.tsx                | 10 ++++++++--
 3 files changed, 10 insertions(+), 4 deletions(-)

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

diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index ca8777de8..a8a2aaa5a 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -67,7 +67,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         Object.values(this._disposers).forEach(disposer => disposer?.());
     }
 
-    componentWillMount() {
+    componentDidMount() {
         this._disposers.autoheight = reaction(() => this.rootDoc.autoHeight,
             auto => auto && this.computeHeight(),
             { fireImmediately: true });
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 8a5425992..827dadae2 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -730,7 +730,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         return this.props.renderedIds.indexOf(this.doc[Id]) !== -1 ? "<" + this.doc.title + ">" : // just print the title of documents we've previously rendered in this hierarchical path to avoid cycles
             <div className={`treeView-container${this.props.isContentActive() ? "-active" : ""}`}
                 ref={this.createTreeDropTarget}
-                onPointerDown={e => this.props.isContentActive(true) && SelectionManager.DeselectAll()}
+                //onPointerDown={e => this.props.isContentActive(true) && SelectionManager.DeselectAll()} // bcz: this breaks entering a text filter in a filterBox since it deselects the filter's target document
                 onKeyDown={this.onKeyDown}>
                 <li className="collection-child">
                     {hideTitle && this.doc.type !== DocumentType.RTF ?
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index 0a010c105..718ebca28 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -217,13 +217,19 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
             });
             let newFacet: Opt<Doc>;
             if (facetHeader === "text" || facetValues.rtFields / allCollectionDocs.length > 0.1) {
-                newFacet = Docs.Create.TextDocument("", { _width: 100, _height: 25, system: true, _stayInCollection: true, treeViewExpandedView: "layout", title: facetHeader, treeViewOpen: true, _forceActive: true, ignoreClick: true });
+                newFacet = Docs.Create.TextDocument("", {
+                    _width: 100, _height: 25, system: true, _stayInCollection: true, target: targetDoc,
+                    treeViewExpandedView: "layout", title: facetHeader, treeViewOpen: true, _forceActive: true, ignoreClick: true
+                });
                 Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox
                 newFacet._textBoxPadding = 4;
                 const scriptText = `setDocFilter(this?.target, "${facetHeader}", text, "match")`;
                 newFacet.onTextChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, text: "string" });
             } else if (facetHeader !== "tags" && nonNumbers / facetValues.strings.length < .1) {
-                newFacet = Docs.Create.SliderDocument({ title: facetHeader, _overflow: "visible", _fitWidth: true, _height: 40, _stayInCollection: true, _hideContextMenu: true, treeViewExpandedView: "layout", treeViewOpen: true });
+                newFacet = Docs.Create.SliderDocument({
+                    title: facetHeader, _overflow: "visible", _fitWidth: true,
+                    _height: 40, _stayInCollection: true, treeViewExpandedView: "layout", treeViewOpen: true
+                });
                 const newFacetField = Doc.LayoutFieldKey(newFacet);
                 const ranged = Doc.readDocRangeFilter(targetDoc, facetHeader);
                 Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox
-- 
cgit v1.2.3-70-g09d2


From 13879075b8347abeecbb178596dc839e7ecdfb54 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 6 Apr 2021 16:41:41 -0400
Subject: switched from context menu to a delete button on filterBox filters. 
 don't select treeView items after expanding them.

---
 src/client/views/collections/TreeView.tsx |  6 ++--
 src/client/views/nodes/FilterBox.tsx      | 56 +++++++++++++++++++------------
 2 files changed, 37 insertions(+), 25 deletions(-)

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

diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 827dadae2..c7322598c 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -152,7 +152,6 @@ export class TreeView extends React.Component<TreeViewProps> {
         } else {
             this.props.addDocTab(this.props.document, "add:right");
         }
-        docView?.select(false);
     }
     constructor(props: any) {
         super(props);
@@ -483,9 +482,9 @@ export class TreeView extends React.Component<TreeViewProps> {
     }
 
     @computed get headerElements() {
-        return this.props.treeViewHideHeaderFields() ? (null)
+        return this.props.treeViewHideHeaderFields() || this.doc.treeViewHideHeaderFields ? (null)
             : <>
-                <FontAwesomeIcon key="bars" icon="bars" size="sm" onClick={e => { this.showContextMenu(e); e.stopPropagation(); }} />
+                {this.doc.hideContextMenu ? (null) : <FontAwesomeIcon key="bars" icon="bars" size="sm" onClick={e => { this.showContextMenu(e); e.stopPropagation(); }} />}
                 {this.doc.treeViewExpandedViewLock || Doc.IsSystem(this.doc) ? (null) :
                     <span className="collectionTreeView-keyHeader" key={this.treeViewExpandedView} onPointerDown={this.expandNextviewType}>
                         {this.treeViewExpandedView}
@@ -526,7 +525,6 @@ export class TreeView extends React.Component<TreeViewProps> {
                 }}>
                     {StrCast(doc?.title)}
                 </div>;
-            case StyleProp.Decorations: return (null);
             default: return this.props?.treeView?.props.styleProvider?.(doc, props, property);
         }
     }
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index e1227b81d..a43b80e5b 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -31,6 +31,7 @@ import { DefaultStyleProvider, StyleProp } from "../StyleProvider";
 import { CollectionViewType } from "../collections/CollectionView";
 import { CurrentUserUtils } from "../../util/CurrentUserUtils";
 import { EditableView } from "../EditableView";
+import { undoBatch } from "../../util/UndoManager";
 
 type FilterBoxDocument = makeInterface<[typeof documentSchema]>;
 const FilterBoxDocument = makeInterface(documentSchema);
@@ -251,10 +252,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
                 newFacet.target = targetDoc;
                 newFacet.data = ComputedField.MakeFunction(`readFacetData(self.target, "${facetHeader}")`);
             }
-            this.props.docViewPath()[0].ComponentView
-            const remove = ScriptField.MakeScript(`documentView.props.removeDocument(self)`, { documentView: "any" });
-            newFacet.contextMenuScripts = new List<ScriptField>([remove!]);
-            newFacet.contextMenuLabels = new List<string>(["Remove"]);
+            newFacet.hideContextMenu = true;
             Doc.AddDocToList(this.dataDoc, this.props.fieldKey, newFacet);
         }
     }
@@ -323,23 +321,21 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
     FilteringStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps | DocumentViewProps>, property: string) {
         switch (property.split(":")[0]) {
             case StyleProp.Decorations:
-                if (doc) {
-                    return doc._viewType === CollectionViewType.Docking || (Doc.IsSystem(doc)) ? (null) :
-                        <>
-                            <div style={{ marginRight: "5px", fontSize: "10px" }}>
-                                <select className="filterBox-selection">
-                                    <option value="Is" key="Is">Is</option>
-                                    <option value="Is Not" key="Is Not">Is Not</option>
-                                </select>
-                            </div>
-                            <div className="filterBox-treeView-close" onClick={e => this.removeFilter(StrCast(doc.title))}>
-                                <FontAwesomeIcon icon={"times"} size="sm" />
-                            </div>
-                        </>;
+                if (doc && !doc.treeViewHideHeaderFields) {
+                    return <>
+                        <div style={{ marginRight: "5px", fontSize: "10px" }}>
+                            <select className="filterBox-selection">
+                                <option value="Is" key="Is">Is</option>
+                                <option value="Is Not" key="Is Not">Is Not</option>
+                            </select>
+                        </div>
+                        <div className="filterBox-treeView-close" onClick={e => this.removeFilter(StrCast(doc.title))}>
+                            <FontAwesomeIcon icon={"times"} size="sm" />
+                        </div>
+                    </>;
                 }
-            default: return DefaultStyleProvider(doc, props, property);
-
         }
+        return DefaultStyleProvider(doc, props, property);
     }
 
     suppressChildClick = () => ScriptField.MakeScript("")!;
@@ -376,6 +372,24 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
         this.layoutDoc._height = hgt + 140; // 50?  need to add all the border sizes together.
     }
 
+    /**
+     * add lock and hide button decorations for the "Dashboards" flyout TreeView
+     */
+    FilterStyleProvider = (doc: Opt<Doc>, props: Opt<FieldViewProps | DocumentViewProps>, property: string) => {
+        switch (property.split(":")[0]) {
+            case StyleProp.Decorations:
+                return !doc || doc.treeViewHideHeaderFields ? (null) : // bcz: Todo: afterHeader should be generalized into a renderPath that is a list of the documents rendered so far which would mimic much of CSS property selectors
+                    <>
+                        <div className={`styleProvider-treeView-hide${doc.hidden ? "-active" : ""}`} onClick={undoBatch(e =>
+                            this.removeFilter(StrCast(doc.title))
+                        )}>
+                            <FontAwesomeIcon icon={"trash"} size="sm" />
+                        </div>
+                    </>;
+        }
+        return this.props.styleProvider?.(doc, props, property);
+    }
+
     layoutHeight = () => this.layoutDoc[HeightSym]();
     render() {
         const facetCollection = this.props.Document;
@@ -431,7 +445,6 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
                     CollectionView={undefined}
                     disableDocBrushing={true}
                     setHeight={this.setTreeHeight} // if the tree view can trigger the height of the filter box to change, then this needs to be filled in.
-                    onChildClick={this.suppressChildClick}
                     docFilters={returnEmptyFilter}
                     docRangeFilters={returnEmptyFilter}
                     searchFilterDocs={returnEmptyDoclist}
@@ -455,7 +468,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
                     treeViewHideHeaderFields={false}
                     onCheckedClick={this.scriptField}
                     dontRegisterView={true}
-                    styleProvider={this.props.styleProvider}
+                    styleProvider={this.FilterStyleProvider}
                     layerProvider={this.props.layerProvider}
                     docViewPath={this.props.docViewPath}
                     scriptContext={this.props.scriptContext}
@@ -530,6 +543,7 @@ Scripting.addGlobal(function readFacetData(layoutDoc: Doc, facetHeader: string)
         doc.target = layoutDoc;
         doc.facetHeader = facetHeader;
         doc.facetValue = facetValue;
+        doc.treeViewHideHeaderFields = true;
         doc.treeViewChecked = ComputedField.MakeFunction("determineCheckedState(self.target, self.facetHeader, self.facetValue)");
         return doc;
     });
-- 
cgit v1.2.3-70-g09d2


From d5b1abae714b4bae0f02ce57a91477bdb2502078 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 6 Apr 2021 17:59:50 -0400
Subject: little cleanup

---
 src/client/views/EditableView.tsx         | 1 -
 src/client/views/StyleProvider.tsx        | 3 ++-
 src/client/views/collections/TreeView.tsx | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

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

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 5daac77ee..03d9efff3 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -47,7 +47,6 @@ export interface EditableProps {
     toggle?: () => void;
     background?: string | undefined;
     placeholder?: string;
-    fullWidth?: boolean; // used in PropertiesView to make the whole key:value input box clickable 
 }
 
 /**
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 3853d5888..d15cd5458 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -69,13 +69,14 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
     const isCaption = property.includes(":caption");
     const isAnchor = property.includes(":anchor");
     const isAnnotated = property.includes(":annotated");
+    const isOpen = property.includes(":open");
     const isBackground = () => StrListCast(doc?._layerTags).includes(StyleLayers.Background);
     const backgroundCol = () => props?.styleProvider?.(doc, props, StyleProp.BackgroundColor);
     const opacity = () => props?.styleProvider?.(doc, props, StyleProp.Opacity);
     const showTitle = () => props?.styleProvider?.(doc, props, StyleProp.ShowTitle);
 
     switch (property.split(":")[0]) {
-        case StyleProp.TreeViewIcon: return doc ? Doc.toIcon(doc) : "question";
+        case StyleProp.TreeViewIcon: return doc?.isFolder ? "chevron-" + (isOpen ? "down" : "right") : doc ? Doc.toIcon(doc) : "question";
         case StyleProp.DocContents: return undefined;
         case StyleProp.WidgetColor: return isAnnotated ? "lightBlue" : darkScheme() ? "lightgrey" : "dimgrey";
         case StyleProp.Opacity: return Cast(doc?._opacity, "number", Cast(doc?.opacity, "number", null));
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index c7322598c..5cf8a6986 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -441,7 +441,7 @@ export class TreeView extends React.Component<TreeViewProps> {
 
     @computed get renderBullet() {
         TraceMobx();
-        const iconType = this.doc.isFolder ? (this.treeViewOpen ? "chevron-down" : "chevron-right") : Doc.toIcon(this.doc);
+        const iconType = this.props.treeView.props.styleProvider?.(this.doc, this.props.treeView.props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ":open" : "")) || "question";
         const checked = this.onCheckedClick ? (this.doc.treeViewChecked ?? "unchecked") : undefined;
         return <div className={`bullet${this.props.treeView.outlineMode ? "-outline" : ""}`} key={"bullet"}
             title={this.childDocs?.length ? `click to see ${this.childDocs?.length} items` : "view fields"}
-- 
cgit v1.2.3-70-g09d2


From fcbe1957d985655167ee8365fbb8f2755bbfd206 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 6 Apr 2021 18:51:01 -0400
Subject: cleanup

---
 src/client/views/collections/CollectionView.tsx | 4 +---
 src/client/views/collections/TreeView.tsx       | 4 ++--
 src/client/views/nodes/DocumentView.tsx         | 4 ++--
 3 files changed, 5 insertions(+), 7 deletions(-)

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

diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 91f159d8e..4dc0ee3e6 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable } from 'mobx';
+import { computed, observable } from 'mobx';
 import { observer } from "mobx-react";
 import * as React from 'react';
 import 'react-image-lightbox-with-rotate/style.css'; // This only needs to be imported once in your app
@@ -35,8 +35,6 @@ import { SubCollectionViewProps } from './CollectionSubView';
 import { CollectionTimeView } from './CollectionTimeView';
 import { CollectionTreeView } from "./CollectionTreeView";
 import './CollectionView.scss';
-import { FilterBox } from '../nodes/FilterBox';
-import { listSpec } from '../../../fields/Schema';
 export const COLLECTION_BORDER_WIDTH = 2;
 const path = require('path');
 
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 5cf8a6986..2cce9c2f5 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -493,9 +493,9 @@ export class TreeView extends React.Component<TreeViewProps> {
     }
 
     showContextMenu = (e: React.MouseEvent) => {
-        DocumentViewInternal.SelectOnContextsMenu = false;
+        DocumentViewInternal.SelectAfterContextMenu = false;
         simulateMouseClick(this._docRef?.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
-        DocumentViewInternal.SelectOnContextsMenu = true;
+        DocumentViewInternal.SelectAfterContextMenu = true;
     }
     contextMenuItems = () => Doc.IsSystem(this.doc) ? [] : this.doc.isFolder ?
         [{ script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" }] :
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 703e78470..5c3d7e415 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -162,6 +162,7 @@ export interface DocumentViewInternalProps extends DocumentViewProps {
 
 @observer
 export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps, Document>(Document) {
+    public static SelectAfterContextMenu = true; //  whether a document should be selected after it's contextmenu is triggered.
     @observable _animateScalingTo = 0;
     @observable _mediaState = 0;
     @observable _pendingDoubleClick = false;
@@ -746,9 +747,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
 
         if (!this.topMost) e?.stopPropagation(); // DocumentViews should stop propagation of this event
         cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15);
-        DocumentViewInternal.SelectOnContextsMenu && !this.props.isSelected(true) && setTimeout(() => SelectionManager.SelectView(this.props.DocumentView(), false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up.  by delaying the selection until hopefully after the pointer up, the context menu will appear.
+        DocumentViewInternal.SelectAfterContextMenu && !this.props.isSelected(true) && setTimeout(() => SelectionManager.SelectView(this.props.DocumentView(), false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up.  by delaying the selection until hopefully after the pointer up, the context menu will appear.
     }
-    public static SelectOnContextsMenu = true;
 
     rootSelected = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false;
     panelHeight = () => this.props.PanelHeight() - this.headerMargin;
-- 
cgit v1.2.3-70-g09d2


From d021eb6fe792e9c76b139b5a706a90a086f3fe53 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 8 Apr 2021 12:59:22 -0400
Subject: made "search" only appear if context menu is > 15 items.

---
 src/client/views/ContextMenu.tsx                   |  27 ++--
 src/client/views/ContextMenuItem.tsx               |   7 +-
 src/client/views/collections/TreeView.tsx          |  17 ++-
 .../collections/collectionFreeForm/MarqueeView.tsx |   2 +-
 src/client/views/nodes/DocumentView.tsx            | 149 +++++++++++----------
 5 files changed, 106 insertions(+), 96 deletions(-)

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

diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index 1f7abf61a..d96de72e3 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -15,6 +15,7 @@ export class ContextMenu extends React.Component {
     @observable private _pageY: number = 0;
     @observable private _display: boolean = false;
     @observable private _searchString: string = "";
+    @observable private _showSearch: boolean = false;
     // afaik displaymenu can be called before all the items are added to the menu, so can't determine in displayMenu what the height of the menu will be
     @observable private _yRelativeToTop: boolean = true;
     @observable selectedIndex = -1;
@@ -137,11 +138,13 @@ export class ContextMenu extends React.Component {
         return y;
     }
 
+
     @action
-    displayMenu = (x: number, y: number, initSearch = "") => {
+    displayMenu = (x: number, y: number, initSearch = "", showSearch = false) => {
         //maxX and maxY will change if the UI/font size changes, but will work for any amount
         //of items added to the menu
 
+        this._showSearch = showSearch;
         this._pageX = x;
         this._pageY = y;
         this._searchString = initSearch;
@@ -215,11 +218,15 @@ export class ContextMenu extends React.Component {
 
     @computed get menuItems() {
         if (!this._searchString) {
-            return this._items.map(item => <ContextMenuItem {...item} key={item.description} closeMenu={this.closeMenu} />);
+            return this._items.map(item => <ContextMenuItem {...item} noexpand={this.itemsNeedSearch ? true : (item as any).noexpand} key={item.description} closeMenu={this.closeMenu} />);
         }
         return this.filteredViews;
     }
 
+    @computed get itemsNeedSearch() {
+        return this._showSearch ? 1 : this._items.reduce((p, mi) => p + ((mi as any).noexpand ? 1 : (mi as any).subitems?.length || 1), 0) > 15;
+    }
+
     render() {
         if (!this._display) {
             return null;
@@ -229,12 +236,13 @@ export class ContextMenu extends React.Component {
 
         const contents = (
             <>
-                <span className={"search-icon"}>
-                    <span className="icon-background">
-                        <FontAwesomeIcon icon="search" size="lg" />
-                    </span>
-                    <input className="contextMenu-item contextMenu-description search" type="text" placeholder="Filter Menu..." value={this._searchString} onKeyDown={this.onKeyDown} onChange={this.onChange} autoFocus />
-                </span>
+                {!this.itemsNeedSearch ? (null) :
+                    <span className={"search-icon"}>
+                        <span className="icon-background">
+                            <FontAwesomeIcon icon="search" size="lg" />
+                        </span>
+                        <input className="contextMenu-item contextMenu-description search" type="text" placeholder="Filter Menu..." value={this._searchString} onKeyDown={this.onKeyDown} onChange={this.onChange} autoFocus />
+                    </span>}
                 {this.menuItems}
             </>
         );
@@ -244,8 +252,7 @@ export class ContextMenu extends React.Component {
                     <div className="contextMenu-cont" style={style} ref={measureRef}>
                         {contents}
                     </div>
-                )
-                }
+                )}
             </Measure>
         );
     }
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index e63631161..6fe2abd21 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -4,7 +4,6 @@ import { observer } from "mobx-react";
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { UndoManager } from "../util/UndoManager";
-import { NumberLiteralType } from "typescript";
 
 export interface OriginalMenuProps {
     description: string;
@@ -33,8 +32,8 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
 
     constructor(props: ContextMenuProps | SubmenuProps) {
         super(props);
-        if ("subitems" in this.props) {
-            this.props.subitems?.forEach(i => this._items.push(i));
+        if ((this.props as SubmenuProps).subitems) {
+            (this.props as SubmenuProps).subitems?.forEach(i => this._items.push(i));
         }
     }
 
@@ -107,7 +106,7 @@ export class ContextMenuItem extends React.Component<ContextMenuProps & { select
                     }}>
                     {this._items.map(prop => <ContextMenuItem {...prop} key={prop.description} closeMenu={this.props.closeMenu} />)}
                 </div>;
-            if (!("noexpand" in this.props)) {
+            if (!(this.props as SubmenuProps).noexpand) {
                 return <div className="contextMenu-inlineMenu">
                     {this._items.map(prop => <ContextMenuItem {...prop} key={prop.description} closeMenu={this.props.closeMenu} />)}
                 </div>;
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 2c3a6c0d7..43f9627e2 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -483,10 +483,10 @@ export class TreeView extends React.Component<TreeViewProps> {
     }
 
     @computed get headerElements() {
-        return this.props.treeViewHideHeaderFields() || Doc.IsSystem(this.doc) ? (null)
+        return this.props.treeViewHideHeaderFields() || (Doc.IsSystem(this.doc) && !this.doc.isFolder) ? (null)
             : <>
                 <FontAwesomeIcon key="bars" icon="bars" size="sm" onClick={e => { this.showContextMenu(e); e.stopPropagation(); }} />
-                {this.doc.treeViewExpandedViewLock ? (null) :
+                {this.doc.isFolder || this.doc.treeViewExpandedViewLock ? (null) :
                     <span className="collectionTreeView-keyHeader" key={this.treeViewExpandedView} onPointerDown={this.expandNextviewType}>
                         {this.treeViewExpandedView}
                     </span>}
@@ -494,11 +494,14 @@ export class TreeView extends React.Component<TreeViewProps> {
     }
 
     showContextMenu = (e: React.MouseEvent) => simulateMouseClick(this._docRef?.ContentDiv, e.clientX, e.clientY + 30, e.screenX, e.screenY + 30);
-    contextMenuItems = () => Doc.IsSystem(this.doc) ? [] : this.doc.isFolder ?
-        [{ script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" }] :
-        this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) ?
-            [{ script: ScriptField.MakeFunction(`openOnRight(getAlias(self))`)!, label: "Open Alias" }] :
-            [{ script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, label: "Focus or Open" }]
+    contextMenuItems = () => {
+        const makeFolder = { script: ScriptField.MakeFunction(`scriptContext.makeFolder()`, { scriptContext: "any" })!, label: "New Folder" };
+        return this.doc.isFolder ? [makeFolder] :
+            Doc.IsSystem(this.doc) ? [] :
+                this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) ?
+                    [{ script: ScriptField.MakeFunction(`openOnRight(getAlias(self))`)!, label: "Open Alias" }, makeFolder] :
+                    [{ script: ScriptField.MakeFunction(`DocFocusOrOpen(self)`)!, label: "Focus or Open" }];
+    }
     onChildClick = () => this.props.onChildClick?.() ?? (this._editTitleScript?.() || ScriptCast(this.doc.treeChildClick));
     onChildDoubleClick = () => (!this.props.treeView.outlineMode && this._openScript?.()) || ScriptCast(this.doc.treeChildDoubleClick);
 
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index d14b68fa7..a4f129b8c 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -101,7 +101,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
             else if (e.key === ":") {
                 DocUtils.addDocumentCreatorMenuItems(this.props.addLiveTextDocument, this.props.addDocument || returnFalse, x, y);
 
-                cm.displayMenu(this._downX, this._downY);
+                cm.displayMenu(this._downX, this._downY, undefined, true);
                 e.stopPropagation();
             } else if (e.key === "a" && (e.ctrlKey || e.metaKey)) {
                 e.preventDefault();
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 26cf52f17..22543cc8a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -660,88 +660,89 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
         this.props.contextMenuItems?.().forEach(item =>
             item.label && cm.addItem({ description: item.label, event: () => item.script.script.run({ this: this.layoutDoc, scriptContext: this.props.scriptContext, self: this.rootDoc }), icon: "sticky-note" }));
 
-        const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null);
-        const appearance = cm.findByDescription("UI Controls...");
-        const appearanceItems: ContextMenuProps[] = appearance && "subitems" in appearance ? appearance.subitems : [];
-        !Doc.UserDoc().noviceMode && templateDoc && appearanceItems.push({ description: "Open Template   ", event: () => this.props.addDocTab(templateDoc, "add:right"), icon: "eye" });
-        DocListCast(this.Document.links).length && appearanceItems.splice(0, 0, { description: `${this.layoutDoc.hideLinkButton ? "Show" : "Hide"} Link Button`, event: action(() => this.layoutDoc.hideLinkButton = !this.layoutDoc.hideLinkButton), icon: "eye" });
-        !appearance && cm.addItem({ description: "UI Controls...", subitems: appearanceItems, icon: "compass" });
-
-        if (!Doc.IsSystem(this.rootDoc) && this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Tree) {
-            !Doc.UserDoc().noviceMode && appearanceItems.splice(0, 0, { description: `${!this.layoutDoc._showAudio ? "Show" : "Hide"} Audio Button`, event: action(() => this.layoutDoc._showAudio = !this.layoutDoc._showAudio), icon: "microphone" });
-            const existingOnClick = cm.findByDescription("OnClick...");
-            const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
-
-            const zorders = cm.findByDescription("ZOrder...");
-            const zorderItems: ContextMenuProps[] = zorders && "subitems" in zorders ? zorders.subitems : [];
-            zorderItems.push({ description: "Bring to Front", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: "expand-arrows-alt" });
-            zorderItems.push({ description: "Send to Back", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" });
-            zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: undoBatch(action(() => this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined)), icon: "expand-arrows-alt" });
-            !zorders && cm.addItem({ description: "ZOrder...", subitems: zorderItems, icon: "compass" });
-
-            onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" });
-            onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "concierge-bell" });
-            onClicks.push({ description: (this.Document.followLinkZoom ? "Don't" : "") + " zoom following link", event: () => this.Document.followLinkZoom = !this.Document.followLinkZoom, icon: this.Document.ignoreClick ? "unlock" : "lock" });
-
-            if (!this.Document.annotationOn) {
-                const options = cm.findByDescription("Options...");
-                const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
-                !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" });
-
-                onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" });
-                onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: () => this.toggleFollowLink("inPlace", true, false), icon: "link" });
-                !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("add:right", false, false), icon: "link" });
-                onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: () => this.toggleFollowLink(undefined, false, false), icon: "link" });
-                onClicks.push({ description: (this.Document.isPushpin ? "Remove" : "Make") + " Pushpin", event: () => this.toggleFollowLink(undefined, false, true), icon: "map-pin" });
-                onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "terminal" });
-                !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, noexpand: true, subitems: onClicks, icon: "mouse-pointer" });
-            } else if (DocListCast(this.Document.links).length) {
-                onClicks.push({ description: "Select on Click", event: () => this.selectOnClick(), icon: "link" });
-                onClicks.push({ description: "Follow Link on Click", event: () => this.followLinkOnClick(undefined, false), icon: "link" });
-                onClicks.push({ description: "Toggle Link Target on Click", event: () => this.toggleTargetOnClick(), icon: "map-pin" });
-                !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, subitems: onClicks, icon: "mouse-pointer" });
+        if (!this.props.Document.isFolder) {
+            const templateDoc = Cast(this.props.Document[StrCast(this.props.Document.layoutKey)], Doc, null);
+            const appearance = cm.findByDescription("UI Controls...");
+            const appearanceItems: ContextMenuProps[] = appearance && "subitems" in appearance ? appearance.subitems : [];
+            !Doc.UserDoc().noviceMode && templateDoc && appearanceItems.push({ description: "Open Template   ", event: () => this.props.addDocTab(templateDoc, "add:right"), icon: "eye" });
+            DocListCast(this.Document.links).length && appearanceItems.splice(0, 0, { description: `${this.layoutDoc.hideLinkButton ? "Show" : "Hide"} Link Button`, event: action(() => this.layoutDoc.hideLinkButton = !this.layoutDoc.hideLinkButton), icon: "eye" });
+            !appearance && cm.addItem({ description: "UI Controls...", subitems: appearanceItems, icon: "compass" });
+
+            if (!Doc.IsSystem(this.rootDoc) && this.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Tree) {
+                !Doc.UserDoc().noviceMode && appearanceItems.splice(0, 0, { description: `${!this.layoutDoc._showAudio ? "Show" : "Hide"} Audio Button`, event: action(() => this.layoutDoc._showAudio = !this.layoutDoc._showAudio), icon: "microphone" });
+                const existingOnClick = cm.findByDescription("OnClick...");
+                const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
+
+                const zorders = cm.findByDescription("ZOrder...");
+                const zorderItems: ContextMenuProps[] = zorders && "subitems" in zorders ? zorders.subitems : [];
+                zorderItems.push({ description: "Bring to Front", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: "expand-arrows-alt" });
+                zorderItems.push({ description: "Send to Back", event: () => SelectionManager.Views().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" });
+                zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: undoBatch(action(() => this.rootDoc._raiseWhenDragged = this.rootDoc._raiseWhenDragged === undefined ? false : undefined)), icon: "expand-arrows-alt" });
+                !zorders && cm.addItem({ description: "ZOrder...", subitems: zorderItems, icon: "compass" });
+
+                onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" });
+                onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "concierge-bell" });
+                onClicks.push({ description: (this.Document.followLinkZoom ? "Don't" : "") + " zoom following link", event: () => this.Document.followLinkZoom = !this.Document.followLinkZoom, icon: this.Document.ignoreClick ? "unlock" : "lock" });
+
+                if (!this.Document.annotationOn) {
+                    const options = cm.findByDescription("Options...");
+                    const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : [];
+                    !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" });
+
+                    onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" });
+                    onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: () => this.toggleFollowLink("inPlace", true, false), icon: "link" });
+                    !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("add:right", false, false), icon: "link" });
+                    onClicks.push({ description: this.Document.isLinkButton || this.onClickHandler ? "Remove Click Behavior" : "Follow Link", event: () => this.toggleFollowLink(undefined, false, false), icon: "link" });
+                    onClicks.push({ description: (this.Document.isPushpin ? "Remove" : "Make") + " Pushpin", event: () => this.toggleFollowLink(undefined, false, true), icon: "map-pin" });
+                    onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "terminal" });
+                    !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, noexpand: true, subitems: onClicks, icon: "mouse-pointer" });
+                } else if (DocListCast(this.Document.links).length) {
+                    onClicks.push({ description: "Select on Click", event: () => this.selectOnClick(), icon: "link" });
+                    onClicks.push({ description: "Follow Link on Click", event: () => this.followLinkOnClick(undefined, false), icon: "link" });
+                    onClicks.push({ description: "Toggle Link Target on Click", event: () => this.toggleTargetOnClick(), icon: "map-pin" });
+                    !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, subitems: onClicks, icon: "mouse-pointer" });
+                }
             }
-        }
 
-        const funcs: ContextMenuProps[] = [];
-        if (!Doc.UserDoc().noviceMode && this.layoutDoc.onDragStart) {
-            funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) });
-            funcs.push({ description: "Drag a Copy", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) });
-            funcs.push({ description: "Drag Document", icon: "edit", event: () => this.layoutDoc.onDragStart = undefined });
-            cm.addItem({ description: "OnDrag...", noexpand: true, subitems: funcs, icon: "asterisk" });
-        }
+            const funcs: ContextMenuProps[] = [];
+            if (!Doc.UserDoc().noviceMode && this.layoutDoc.onDragStart) {
+                funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) });
+                funcs.push({ description: "Drag a Copy", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) });
+                funcs.push({ description: "Drag Document", icon: "edit", event: () => this.layoutDoc.onDragStart = undefined });
+                cm.addItem({ description: "OnDrag...", noexpand: true, subitems: funcs, icon: "asterisk" });
+            }
 
-        const more = cm.findByDescription("More...");
-        const moreItems = more && "subitems" in more ? more.subitems : [];
-        if (!Doc.IsSystem(this.rootDoc)) {
-            (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.UserDoc().noviceMode) && moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: "users" });
-            if (!Doc.UserDoc().noviceMode) {
-                moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" });
-                moreItems.push({ description: `${this.Document._chromeHidden ? "Show" : "Hide"} Chrome`, event: () => this.Document._chromeHidden = !this.Document._chromeHidden, icon: "project-diagram" });
-
-                if (Cast(Doc.GetProto(this.props.Document).data, listSpec(Doc))) {
-                    moreItems.push({ description: "Export to Google Photos Album", event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this.props.Document }).then(console.log), icon: "caret-square-right" });
-                    moreItems.push({ description: "Tag Child Images via Google Photos", event: () => GooglePhotos.Query.TagChildImages(this.props.Document), icon: "caret-square-right" });
-                    moreItems.push({ description: "Write Back Link to Album", event: () => GooglePhotos.Transactions.AddTextEnrichment(this.props.Document), icon: "caret-square-right" });
+            const more = cm.findByDescription("More...");
+            const moreItems = more && "subitems" in more ? more.subitems : [];
+            if (!Doc.IsSystem(this.rootDoc)) {
+                (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.UserDoc().noviceMode) && moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: "users" });
+                if (!Doc.UserDoc().noviceMode) {
+                    moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" });
+                    moreItems.push({ description: `${this.Document._chromeHidden ? "Show" : "Hide"} Chrome`, event: () => this.Document._chromeHidden = !this.Document._chromeHidden, icon: "project-diagram" });
+
+                    if (Cast(Doc.GetProto(this.props.Document).data, listSpec(Doc))) {
+                        moreItems.push({ description: "Export to Google Photos Album", event: () => GooglePhotos.Export.CollectionToAlbum({ collection: this.props.Document }).then(console.log), icon: "caret-square-right" });
+                        moreItems.push({ description: "Tag Child Images via Google Photos", event: () => GooglePhotos.Query.TagChildImages(this.props.Document), icon: "caret-square-right" });
+                        moreItems.push({ description: "Write Back Link to Album", event: () => GooglePhotos.Transactions.AddTextEnrichment(this.props.Document), icon: "caret-square-right" });
+                    }
+                    moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" });
                 }
-                moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" });
             }
-        }
-
-        if (this.props.removeDocument && !Doc.IsSystem(this.rootDoc) && CurrentUserUtils.ActiveDashboard !== this.props.Document) { // need option to gray out menu items ... preferably with a '?' that explains why they're grayed out (eg., no permissions)
-            moreItems.push({ description: "Close", event: this.deleteClicked, icon: "times" });
-        }
 
-        !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" });
-        cm.moveAfter(cm.findByDescription("More...")!, cm.findByDescription("OnClick...")!);
+            if (this.props.removeDocument && !Doc.IsSystem(this.rootDoc) && CurrentUserUtils.ActiveDashboard !== this.props.Document) { // need option to gray out menu items ... preferably with a '?' that explains why they're grayed out (eg., no permissions)
+                moreItems.push({ description: "Close", event: this.deleteClicked, icon: "times" });
+            }
 
-        const help = cm.findByDescription("Help...");
-        const helpItems: ContextMenuProps[] = help && "subitems" in help ? help.subitems : [];
-        !Doc.UserDoc().novice && helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "add:right"), icon: "layer-group" });
-        helpItems.push({ description: "Text Shortcuts Ctrl+/", event: () => this.props.addDocTab(Docs.Create.PdfDocument(Utils.prepend("/assets/cheat-sheet.pdf"), { _width: 300, _height: 300 }), "add:right"), icon: "keyboard" });
-        !Doc.UserDoc().novice && helpItems.push({ description: "Print Document in Console", event: () => console.log(this.props.Document), icon: "hand-point-right" });
-        cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" });
+            !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" });
+            cm.moveAfter(cm.findByDescription("More...")!, cm.findByDescription("OnClick...")!);
 
+            const help = cm.findByDescription("Help...");
+            const helpItems: ContextMenuProps[] = help && "subitems" in help ? help.subitems : [];
+            !Doc.UserDoc().novice && helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "add:right"), icon: "layer-group" });
+            helpItems.push({ description: "Text Shortcuts Ctrl+/", event: () => this.props.addDocTab(Docs.Create.PdfDocument(Utils.prepend("/assets/cheat-sheet.pdf"), { _width: 300, _height: 300 }), "add:right"), icon: "keyboard" });
+            !Doc.UserDoc().novice && helpItems.push({ description: "Print Document in Console", event: () => console.log(this.props.Document), icon: "hand-point-right" });
+            cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" });
+        }
         if (!this.topMost) e?.stopPropagation(); // DocumentViews should stop propagation of this event
         cm.displayMenu((e?.pageX || pageX || 0) - 15, (e?.pageY || pageY || 0) - 15);
         !this.props.isSelected(true) && setTimeout(() => SelectionManager.SelectView(this.props.DocumentView(), false), 300); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up.  by delaying the selection until hopefully after the pointer up, the context menu will appear.
-- 
cgit v1.2.3-70-g09d2


From ffcb1cdf35e1f666034a1471cdd757c64b03ab52 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 8 Apr 2021 13:51:18 -0400
Subject: from last

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

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

diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 43f9627e2..a4d734a70 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -545,7 +545,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             }
         }
     }
-    titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth() - treeBulletWidth()));
+    titleWidth = () => Math.max(20, Math.min(this.props.treeView.truncateTitleWidth(), this.props.panelWidth() - 2 * treeBulletWidth()));
 
     /**
      * Renders the EditableView title element for placement into the tree.
-- 
cgit v1.2.3-70-g09d2


From 07ad05653c419a197a58a4f076f4d63697c375d9 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 12 Apr 2021 13:43:34 -0400
Subject: added placeholder comment

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

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

diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index ce3ba7981..e1fd78270 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -150,6 +150,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         if (this.props.document.isFolder || Doc.IsSystem(this.props.document)) {
             this.treeViewOpen = !this.treeViewOpen;
         } else {
+            // choose an appropriate alias or make one. --- choose the first alias that (1) user owns,  (2) has no context field ... otherwise make a new alias
             this.props.addDocTab(this.props.document, "add:right");
         }
     }
-- 
cgit v1.2.3-70-g09d2

