From 7035e2e6bdcb3efbfa3a4eca887b41eba87e6d6e Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 23 Feb 2021 01:53:52 -0500
Subject: fixed backspace to delete text items in treeViews.  simplified
 UndoRunInTempBatch.  fixed clicking on sort line for treeView to only
 recognize actual clicks.  fixed stayInCollection with DocDecorations to not
 create a giant gray square.  prevent server crash when db has bad data
 somehow.

---
 src/client/views/collections/TreeView.tsx | 52 +++++++++++++++----------------
 1 file changed, 25 insertions(+), 27 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 aed6302ad..00e9456a1 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -39,14 +39,14 @@ export interface TreeViewProps {
     containingCollection: Doc;
     prevSibling?: Doc;
     renderDepth: number;
-    removeDoc: ((doc: Doc | Doc[]) => boolean) | undefined;
-    moveDocument: DragManager.MoveFunction;
     dropAction: dropActionType;
     addDocTab: (doc: Doc, where: string) => boolean;
     pinToPres: (document: Doc) => void;
     panelWidth: () => number;
     panelHeight: () => number;
     addDocument: (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => boolean;
+    removeDoc: ((doc: Doc | Doc[]) => boolean) | undefined;
+    moveDocument: DragManager.MoveFunction;
     indentDocument?: (editTitle: boolean) => void;
     outdentDocument?: (editTitle: boolean) => void;
     ScreenToLocalTransform: () => Transform;
@@ -263,20 +263,15 @@ export class TreeView extends React.Component<TreeViewProps> {
             e.stopPropagation();
             if (docDragData.draggedDocuments[0] === this.doc) return true;
             const parentAddDoc = (doc: Doc | Doc[]) => this.props.addDocument(doc, undefined, before);
-            let addDoc = parentAddDoc;
-            if (inside) {
-                const localAdd = (doc: Doc) => {
-                    const added = Doc.AddDocToList(this.dataDoc, this.fieldKey, doc);
-                    added && (doc.context = this.doc.context);
-                    return added;
-                };
-                addDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce(
-                    (flg: boolean, doc) => flg && localAdd(doc), true) || parentAddDoc(doc);
-            }
+            const canAdd = !StrCast((inside ? this.props.document : this.props.containingCollection)?.freezeChildren).includes("add") || docDragData.treeViewDoc === this.props.treeView.props.Document;
+            const localAdd = (doc: Doc) => Doc.AddDocToList(this.dataDoc, this.fieldKey, doc) && ((doc.context = this.doc.context) || true) ? true : false;
+            const addDoc = !inside ? parentAddDoc :
+                (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc), true as boolean);
             const move = (!docDragData.dropAction || docDragData.dropAction === "move" || docDragData.dropAction === "same") && docDragData.moveDocument;
-            return docDragData.droppedDocuments.reduce((added, d) => (move ? docDragData.moveDocument?.(d, undefined, addDoc) : addDoc(d)) || added, false);
+            if (canAdd) {
+                UndoManager.RunInTempBatch(() => docDragData.droppedDocuments.reduce((added, d) => (move ? move(d, undefined, addDoc) : addDoc(d)) || added, false));
+            }
         }
-        return false;
     }
 
     refTransform = (ref: HTMLDivElement | undefined | null) => {
@@ -401,16 +396,19 @@ export class TreeView extends React.Component<TreeViewProps> {
             const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true);
             const docs = expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs;
             const sortKey = `${this.fieldKey}-sortCriteria`;
-            return <ul key={expandKey + "more"} className={this.doc.treeViewHideTitle ? "no-indent" : ""} onClick={(e) => {
-                if (this.props.active()) {
-                    !this.outlineMode && (this.doc[sortKey] =
-                        (this.doc[sortKey] === "ascending" ? "descending" :
-                            (this.doc[sortKey] === "descending" ? "zorder" :
-                                (this.doc[sortKey] === "zorder" ? undefined :
-                                    "ascending"))));
-                    e.stopPropagation();
-                }
-            }}>
+            let downX = 0, downY = 0;
+            return <ul key={expandKey + "more"} className={this.doc.treeViewHideTitle ? "no-indent" : ""}
+                onPointerDown={e => { downX = e.clientX; downY = e.clientY; }}
+                onClick={(e) => {
+                    if (this.props.active() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) {
+                        !this.outlineMode && (this.doc[sortKey] =
+                            (this.doc[sortKey] === "ascending" ? "descending" :
+                                (this.doc[sortKey] === "descending" ? "zorder" :
+                                    (this.doc[sortKey] === "zorder" ? undefined :
+                                        "ascending"))));
+                        e.stopPropagation();
+                    }
+                }}>
                 {!docs ? (null) :
                     TreeView.GetChildElements(docs, this.props.treeView, this.layoutDoc,
                         this.dataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move,
@@ -571,7 +569,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             : <DocumentView key="title"
                 ref={action((r: any) => {
                     this._docRef = r ? r : undefined;
-                    if (this._docRef && TreeView._editTitleOnLoad?.id === this.props.document[Id] && TreeView._editTitleOnLoad.parent == this.props.parentTreeView) {
+                    if (this._docRef && TreeView._editTitleOnLoad?.id === this.props.document[Id] && TreeView._editTitleOnLoad.parent === this.props.parentTreeView) {
                         this._docRef.select(false);
                         this.setEditTitle(this._docRef);
                         TreeView._editTitleOnLoad = undefined;
@@ -772,7 +770,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         parentCollectionDoc: Doc | undefined,
         parentPrevSibling: Doc | undefined,
         add: (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => boolean,
-        remove: ((doc: Doc | Doc[]) => boolean),
+        remove: undefined | ((doc: Doc | Doc[]) => boolean),
         move: DragManager.MoveFunction,
         dropAction: dropActionType,
         addDocTab: (doc: Doc, where: string) => boolean,
@@ -818,7 +816,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                     newParent.treeViewOpen = true;
                     child.context = treeView.Document;
                 }
-            }
+            };
             const indent = i === 0 ? undefined : (editTitle: boolean) => dentDoc(editTitle, docs[i - 1], undefined, treeViewRefs.get(docs[i - 1]));
             const outdent = parentCollectionDoc?._viewType !== CollectionViewType.Tree ? undefined : ((editTitle: boolean) => dentDoc(editTitle, parentCollectionDoc, parentPrevSibling, parentTreeView instanceof TreeView ? parentTreeView.props.parentTreeView : undefined));
             const addDocument = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => add(doc, relativeTo ?? docs[i], before !== undefined ? before : false);
-- 
cgit v1.2.3-70-g09d2


From 77b1f624f24e055c498e3104fc84227a545a05b9 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 23 Feb 2021 02:22:00 -0500
Subject: clean up from last.

---
 src/client/views/collections/TreeView.tsx | 30 ++++++++++++++----------------
 1 file changed, 14 insertions(+), 16 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 00e9456a1..ec8e63b6c 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -382,7 +382,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 // if there's a sort ordering specified that can be modified on drop (eg, zorder can be modified, alphabetical can't),
                 // then the modification would be done here
                 const ordering = StrCast(this.doc[this.fieldKey + "-sortCriteria"]);
-                if (ordering === "zorder") {
+                if (ordering === "Z") {
                     const docs = TreeView.sortDocs(this.childDocs || ([] as Doc[]), ordering);
                     doc.zIndex = addBefore ? (before ? NumCast(addBefore.zIndex) - 0.5 : NumCast(addBefore.zIndex) + 0.5) : 1000;
                     docs.push(doc);
@@ -397,15 +397,13 @@ export class TreeView extends React.Component<TreeViewProps> {
             const docs = expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs;
             const sortKey = `${this.fieldKey}-sortCriteria`;
             let downX = 0, downY = 0;
-            return <ul key={expandKey + "more"} className={this.doc.treeViewHideTitle ? "no-indent" : ""}
-                onPointerDown={e => { downX = e.clientX; downY = e.clientY; }}
+            const sortings = ["up", "down", "Z", undefined];
+            const curSort = Math.max(0, sortings.indexOf(Cast(this.doc[sortKey], "string", null)));
+            return <ul key={expandKey + "more"} title={"sort: " + sortings[curSort]} className={this.doc.treeViewHideTitle ? "no-indent" : ""}
+                onPointerDown={e => { downX = e.clientX; downY = e.clientY; e.stopPropagation(); }}
                 onClick={(e) => {
                     if (this.props.active() && Math.abs(e.clientX - downX) < 3 && Math.abs(e.clientY - downY) < 3) {
-                        !this.outlineMode && (this.doc[sortKey] =
-                            (this.doc[sortKey] === "ascending" ? "descending" :
-                                (this.doc[sortKey] === "descending" ? "zorder" :
-                                    (this.doc[sortKey] === "zorder" ? undefined :
-                                        "ascending"))));
+                        !this.outlineMode && (this.doc[sortKey] = sortings[(curSort + 1) % sortings.length]);
                         e.stopPropagation();
                     }
                 }}>
@@ -461,9 +459,9 @@ export class TreeView extends React.Component<TreeViewProps> {
                     <div className={`treeView-${this.onCheckedClick ? "checkIcon" : "expandIcon"}`}>
                         <FontAwesomeIcon size="sm" icon={
                             checked === "check" ? "check" :
-                                (checked === "x" ? "times" : checked === "unchecked" ? "square" :
-                                    !this.treeViewOpen ? "caret-right" :
-                                        "caret-down")} />
+                                checked === "x" ? "times" :
+                                    checked === "unchecked" ? "square" :
+                                        !this.treeViewOpen ? "caret-right" : "caret-down"} />
                     </div>
                     {this.onCheckedClick ? (null) : <FontAwesomeIcon icon={iconType} />}
                 </div>
@@ -701,7 +699,7 @@ export class TreeView extends React.Component<TreeViewProps> {
     @computed get renderBorder() {
         const sorting = this.doc[`${this.fieldKey}-sortCriteria`];
         return <div className={`treeView-border${this.outlineMode ? "outline" : ""}`}
-            style={{ borderColor: sorting === undefined ? undefined : sorting === "ascending" ? "crimson" : sorting === "descending" ? "blue" : "green" }}>
+            style={{ borderColor: sorting === undefined ? undefined : sorting === "up" ? "crimson" : sorting === "down" ? "blue" : "green" }}>
             {!this.treeViewOpen ? (null) : this.renderContent}
         </div>;
     }
@@ -749,10 +747,10 @@ export class TreeView extends React.Component<TreeViewProps> {
                 }
             };
             docs.sort(function (d1, d2): 0 | 1 | -1 {
-                const a = (criterion === "ascending" ? d2 : d1);
-                const b = (criterion === "ascending" ? d1 : d2);
-                const first = a[criterion === "zorder" ? "zIndex" : "title"];
-                const second = b[criterion === "zorder" ? "zIndex" : "title"];
+                const a = (criterion === "up" ? d2 : d1);
+                const b = (criterion === "up" ? d1 : d2);
+                const first = a[criterion === "Z" ? "zIndex" : "title"];
+                const second = b[criterion === "Z" ? "zIndex" : "title"];
                 if (typeof first === 'number' && typeof second === 'number') return (first - second) > 0 ? 1 : -1;
                 if (typeof first === 'string' && typeof second === 'string') return sortAlphaNum(first, second);
                 return criterion ? 1 : -1;
-- 
cgit v1.2.3-70-g09d2


From ee2f9feea2ec70dbf5a60d2b26a61b05eca3dbf5 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 23 Feb 2021 10:23:26 -0500
Subject: cleaned up EditableView a bit

---
 src/client/views/EditableView.tsx                  | 59 +++++-----------------
 .../collections/CollectionMasonryViewFieldRow.tsx  | 35 ++++++-------
 .../CollectionStackingViewFieldColumn.tsx          | 33 +++++-------
 .../views/collections/CollectionTimeView.tsx       | 32 ++++++------
 src/client/views/collections/TreeView.tsx          |  1 +
 src/client/views/nodes/KeyValuePair.tsx            |  7 +--
 src/client/views/nodes/LinkDescriptionPopup.tsx    |  1 -
 src/debug/Viewer.tsx                               |  3 +-
 8 files changed, 63 insertions(+), 108 deletions(-)

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

diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index ed7a8265f..e2f171f9d 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -3,8 +3,6 @@ import { action, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as Autosuggest from 'react-autosuggest';
 import { ObjectField } from '../../fields/ObjectField';
-import { SchemaHeaderField } from '../../fields/SchemaHeaderField';
-import { DragManager } from '../util/DragManager';
 import "./EditableView.scss";
 
 export interface EditableProps {
@@ -12,16 +10,13 @@ export interface EditableProps {
      * Called to get the initial value for editing
      *  */
     GetValue(): string | undefined;
-
     /**
      * Called to apply changes
      * @param value - The string entered by the user to set the value to
      * @returns `true` if setting the value was successful, `false` otherwise
      *  */
     SetValue(value: string, shiftDown?: boolean, enterKey?: boolean): boolean;
-
     OnFillDown?(value: string): void;
-
     OnTab?(shift?: boolean): void;
     OnEmpty?(): void;
 
@@ -45,15 +40,12 @@ export interface EditableProps {
     };
     oneLine?: boolean;
     editing?: boolean;
-    onClick?: (e: React.MouseEvent) => boolean;
     isEditingCallback?: (isEditing: boolean) => void;
     menuCallback?: (x: number, y: number) => void;
     textCallback?: (char: string) => boolean;
     showMenuOnLoad?: boolean;
-    HeadingObject?: SchemaHeaderField | undefined;
     toggle?: () => void;
-    color?: string | undefined;
-    onDrop?: any;
+    background?: string | undefined;
     placeholder?: string;
 }
 
@@ -64,6 +56,8 @@ export interface EditableProps {
  */
 @observer
 export class EditableView extends React.Component<EditableProps> {
+    private _ref = React.createRef<HTMLDivElement>();
+    private _inputref = React.createRef<HTMLInputElement>();
     @observable _editing: boolean = false;
 
     constructor(props: EditableProps) {
@@ -71,17 +65,6 @@ export class EditableView extends React.Component<EditableProps> {
         this._editing = this.props.editing ? true : false;
     }
 
-    // @action
-    // componentDidUpdate(nextProps: EditableProps) {
-    //     // this is done because when autosuggest is turned on, the suggestions are passed in as a prop,
-    //     // so when the suggestions are passed in, and no editing prop is passed in, it used to set it
-    //     // to false. this will no longer do so -syip
-    //     if (nextProps.editing && nextProps.editing !== this._editing) {
-    //         this._editing = nextProps.editing;
-    //         EditableView.loadId = "";
-    //     }
-    // }
-
     @action
     componentDidUpdate() {
         if (this._editing && this.props.editing === false) {
@@ -91,19 +74,10 @@ export class EditableView extends React.Component<EditableProps> {
         }
     }
 
-    @action
-    componentDidMount() {
-        if (this._ref.current && this.props.onDrop) {
-            DragManager.MakeDropTarget(this._ref.current, this.props.onDrop.bind(this));
-        }
-    }
-    @action
     componentWillUnmount() {
         this._inputref.current?.value && this.finalizeEdit(this._inputref.current.value, false, true, false);
     }
 
-    _didShow = false;
-
     @action
     onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
         switch (e.key) {
@@ -149,7 +123,7 @@ export class EditableView extends React.Component<EditableProps> {
             e.nativeEvent.stopPropagation();
             if (this._ref.current && this.props.showMenuOnLoad) {
                 this.props.menuCallback?.(this._ref.current.getBoundingClientRect().x, this._ref.current.getBoundingClientRect().y);
-            } else if (!this.props.onClick?.(e)) {
+            } else {
                 this._editing = true;
                 this.props.isEditingCallback?.(true);
             }
@@ -158,7 +132,7 @@ export class EditableView extends React.Component<EditableProps> {
     }
 
     @action
-    private finalizeEdit(value: string, shiftDown: boolean, lostFocus: boolean, enterKey: boolean) {
+    finalizeEdit(value: string, shiftDown: boolean, lostFocus: boolean, enterKey: boolean) {
         if (this.props.SetValue(value, shiftDown, enterKey)) {
             this._editing = false;
             this.props.isEditingCallback?.(false,);
@@ -172,9 +146,7 @@ export class EditableView extends React.Component<EditableProps> {
         }
     }
 
-    stopPropagation(e: React.SyntheticEvent) {
-        e.stopPropagation();
-    }
+    stopPropagation(e: React.SyntheticEvent) { e.stopPropagation(); }
 
     @action
     setIsFocused = (value: boolean) => {
@@ -183,8 +155,6 @@ export class EditableView extends React.Component<EditableProps> {
         return wasFocused !== this._editing;
     }
 
-    _ref = React.createRef<HTMLDivElement>();
-    _inputref = React.createRef<HTMLInputElement>();
     renderEditor() {
         return this.props.autosuggestProps
             ? <Autosuggest
@@ -203,14 +173,13 @@ export class EditableView extends React.Component<EditableProps> {
                 }}
             />
             : <input className="editableView-input" ref={this._inputref}
+                style={{ display: this.props.display, fontSize: this.props.fontSize, minWidth: 20, background: this.props.background }}
+                placeholder={this.props.placeholder}
+                onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true, false)}
                 defaultValue={this.props.GetValue()}
-                onKeyDown={this.onKeyDown}
                 autoFocus={true}
-                onKeyPress={e => e.stopPropagation()}
-                onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true, false)}
-                onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation}
-                style={{ display: this.props.display, fontSize: this.props.fontSize, minWidth: 20 }}
-                placeholder={this.props.placeholder}
+                onKeyDown={this.onKeyDown}
+                onKeyPress={this.stopPropagation} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation}
             />;
     }
 
@@ -225,13 +194,13 @@ export class EditableView extends React.Component<EditableProps> {
                 </div> :
                 this.renderEditor();
         }
-        setTimeout(() => this.props.autosuggestProps?.resetValue(), 0);
+        setTimeout(() => this.props.autosuggestProps?.resetValue());
         return this.props.contents instanceof ObjectField ? (null) :
             <div className={`editableView-container-editing${this.props.oneLine ? "-oneLine" : ""}`} ref={this._ref}
                 style={{ display: this.props.display, textOverflow: this.props.overflow, minHeight: "17px", whiteSpace: "nowrap", height: this.props.height || "auto", maxHeight: this.props.maxHeight }}
                 onClick={this.onClick} placeholder={this.props.placeholder}>
-                <span style={{ fontStyle: this.props.fontStyle, fontSize: this.props.fontSize }} >{
-                    this.props.contents ? this.props.contents?.valueOf() : this.props.placeholder?.valueOf()}
+                <span style={{ fontStyle: this.props.fontStyle, fontSize: this.props.fontSize }} >
+                    {this.props.contents ? this.props.contents?.valueOf() : this.props.placeholder?.valueOf()}
                 </span>
             </div>;
     }
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index ff69c7d05..4bdd39194 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -6,7 +6,7 @@ import { Doc, DocListCast, DataSym } from "../../../fields/Doc";
 import { PastelSchemaPalette, SchemaHeaderField } from "../../../fields/SchemaHeaderField";
 import { ScriptField } from "../../../fields/ScriptField";
 import { StrCast, NumCast } from "../../../fields/Types";
-import { numberRange, setupMoveUpEvents, emptyFunction } from "../../../Utils";
+import { numberRange, setupMoveUpEvents, emptyFunction, returnEmptyString } from "../../../Utils";
 import { Docs } from "../../documents/Documents";
 import { DragManager } from "../../util/DragManager";
 import { CompileScript } from "../../util/Scripting";
@@ -249,14 +249,6 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
         const rows = Math.max(1, Math.min(this.props.docList.length, Math.floor((this.props.parent.props.PanelWidth() - 2 * this.props.parent.xMargin) / (this.props.parent.columnWidth + this.props.parent.gridGap))));
         const style = this.props.parent;
         const chromeStatus = this.props.parent.props.Document._chromeStatus;
-        const newEditableViewProps = {
-            GetValue: () => "",
-            SetValue: this.addDocument,
-            textCallback: this.textCallback,
-            contents: "+ NEW",
-            HeadingObject: this.props.headingObject,
-            toggle: this.toggleVisibility,
-        };
         const showChrome = (chromeStatus !== 'view-mode' && chromeStatus !== 'disabled');
         const stackPad = showChrome ? `0px ${this.props.parent.xMargin}px` : `${this.props.parent.yMargin}px ${this.props.parent.xMargin}px 0px ${this.props.parent.xMargin}px `;
         return this.collapsed ? (null) :
@@ -267,7 +259,12 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
                             //width: style.columnWidth / style.numGroupColumns,
                             padding: `${NumCast(this.props.parent.layoutDoc._yPadding, this.props.parent.yMargin)}px 0px 0px 0px`
                         }}>
-                        <EditableView {...newEditableViewProps} />
+                        <EditableView
+                            GetValue={returnEmptyString}
+                            SetValue={this.addDocument}
+                            textCallback={this.textCallback}
+                            contents={"+ NEW"}
+                            toggle={this.toggleVisibility} />
                     </div> : null
                 }
                 <div className={`collectionStackingView-masonryGrid`}
@@ -288,17 +285,15 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
         const noChrome = this.props.parent.props.Document._chromeStatus === "disabled";
         const key = StrCast(this.props.parent.props.Document._pivotField);
         const evContents = this.heading ? this.heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`;
-        const headerEditableViewProps = {
-            GetValue: () => evContents,
-            SetValue: this.headingChanged,
-            contents: evContents,
-            oneLine: true,
-            HeadingObject: this.props.headingObject,
-            toggle: this.toggleVisibility,
-        };
+        const editableHeaderView = <EditableView
+            GetValue={() => evContents}
+            SetValue={this.headingChanged}
+            contents={evContents}
+            oneLine={true}
+            toggle={this.toggleVisibility} />;
         return this.props.parent.props.Document.miniHeaders ?
             <div className="collectionStackingView-miniHeader">
-                <EditableView {...headerEditableViewProps} />
+                {editableHeaderView}
             </div> :
             !this.props.headingObject ? (null) :
                 <div className="collectionStackingView-sectionHeader" ref={this._headerRef} >
@@ -306,7 +301,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
                         title={evContents === `NO ${key.toUpperCase()} VALUE` ?
                             `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ""}
                         style={{ background: evContents !== `NO ${key.toUpperCase()} VALUE` ? this.color : "lightgrey" }}>
-                        {noChrome ? evContents : <EditableView {...headerEditableViewProps} />}
+                        {noChrome ? evContents : editableHeaderView}
                         {noChrome || evContents === `NO ${key.toUpperCase()} VALUE` ? (null) :
                             <div className="collectionStackingView-sectionColor">
                                 <button className="collectionStackingView-sectionColorButton" onClick={action(e => this._paletteOn = !this._paletteOn)}>
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index ec6458d00..0182c2625 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -10,7 +10,7 @@ import { ScriptField } from "../../../fields/ScriptField";
 import { Cast, NumCast, StrCast } from "../../../fields/Types";
 import { ImageField } from "../../../fields/URLField";
 import { TraceMobx } from "../../../fields/util";
-import { emptyFunction, setupMoveUpEvents, returnFalse } from "../../../Utils";
+import { emptyFunction, setupMoveUpEvents, returnFalse, returnEmptyString } from "../../../Utils";
 import { Docs, DocUtils } from "../../documents/Documents";
 import { DocumentType } from "../../documents/DocumentTypes";
 import { DragManager } from "../../util/DragManager";
@@ -294,22 +294,6 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
         const columnYMargin = this.props.headingObject ? 0 : NumCast(this.props.parent.yMargin, 5);
         const uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
         const evContents = heading ? heading : this.props?.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`;
-        const headerEditableViewProps = {
-            GetValue: () => evContents,
-            SetValue: this.headingChanged,
-            contents: evContents,
-            oneLine: true,
-            HeadingObject: this.props.headingObject,
-            toggle: this.toggleVisibility,
-        };
-        const newEditableViewProps = {
-            GetValue: () => "",
-            SetValue: this.addDocument,
-            textCallback: this.textCallback,
-            contents: "+ NEW",
-            HeadingObject: this.props.headingObject,
-            toggle: this.toggleVisibility,
-        };
         const headingView = this.props.headingObject ?
             <div key={heading} className="collectionStackingView-sectionHeader" ref={this._headerRef}
                 style={{
@@ -325,7 +309,12 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                     title={evContents === `NO ${key.toUpperCase()} VALUE` ?
                         `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ""}
                     style={{ background: evContents !== `NO ${key.toUpperCase()} VALUE` ? this._color : "inherit" }}>
-                    <EditableView {...headerEditableViewProps} />
+                    <EditableView
+                        GetValue={() => evContents}
+                        SetValue={this.headingChanged}
+                        contents={evContents}
+                        oneLine={true}
+                        toggle={this.toggleVisibility} />
                     {evContents === `NO ${key.toUpperCase()} VALUE` ? (null) :
                         <div className="collectionStackingView-sectionColor">
                             <button className="collectionStackingView-sectionColorButton" onClick={action(e => this._paletteOn = !this._paletteOn)}>
@@ -373,7 +362,13 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                         {(chromeStatus !== 'view-mode' && chromeStatus !== 'disabled' && type !== DocumentType.PRES) ?
                             <div key={`${heading}-add-document`} className="collectionStackingView-addDocumentButton"
                                 style={{ width: style.columnWidth / style.numGroupColumns, marginBottom: 10 }}>
-                                <EditableView {...newEditableViewProps} menuCallback={this.menuCallback} />
+                                <EditableView
+                                    GetValue={returnEmptyString}
+                                    SetValue={this.addDocument}
+                                    textCallback={this.textCallback}
+                                    contents={"+ NEW"}
+                                    toggle={this.toggleVisibility}
+                                    menuCallback={this.menuCallback} />
                             </div> : null}
                     </div>
             }
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index cd91cbf63..857d5e1d7 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -8,7 +8,7 @@ import { RichTextField } from "../../../fields/RichTextField";
 import { listSpec } from "../../../fields/Schema";
 import { ComputedField, ScriptField } from "../../../fields/ScriptField";
 import { Cast, NumCast, StrCast } from "../../../fields/Types";
-import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents } from "../../../Utils";
+import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents, returnEmptyString } from "../../../Utils";
 import { Docs, DocUtils } from "../../documents/Documents";
 import { DocumentManager } from "../../util/DocumentManager";
 import { Scripting } from "../../util/Scripting";
@@ -193,22 +193,22 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) {
     }
 
     @computed get pivotKeyUI() {
-        const newEditableViewProps = {
-            GetValue: () => "",
-            SetValue: (value: any) => {
-                if (value?.length) {
-                    this.layoutDoc._pivotField = value;
-                    return true;
-                }
-                return false;
-            },
-            showMenuOnLoad: true,
-            contents: ":" + StrCast(this.layoutDoc._pivotField),
-            toggle: this.toggleVisibility,
-            color: "#f1efeb" // this.props.headingObject ? this.props.headingObject.color : "#f1efeb";
-        };
         return <div className={"pivotKeyEntry"}>
-            <EditableView {...newEditableViewProps} display={"inline"} menuCallback={this.menuCallback} />
+            <EditableView
+                GetValue={returnEmptyString}
+                SetValue={(value: any) => {
+                    if (value?.length) {
+                        this.layoutDoc._pivotField = value;
+                        return true;
+                    }
+                    return false;
+                }}
+                toggle={this.toggleVisibility}
+                background={"#f1efeb"} // this.props.headingObject ? this.props.headingObject.color : "#f1efeb";
+                contents={":" + StrCast(this.layoutDoc._pivotField)}
+                showMenuOnLoad={true}
+                display={"inline"}
+                menuCallback={this.menuCallback} />
         </div>;
     }
 
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index ec8e63b6c..297796b4b 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -548,6 +548,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             oneLine={true}
             display={"inline-block"}
             editing={true}
+            background={"#7089bb"}
             contents={StrCast(this.doc.title)}
             height={12}
             sizeToContent={true}
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index ce9d8bed5..ebb953dad 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -125,12 +125,9 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
                             contents={contents}
                             maxHeight={36}
                             height={"auto"}
-                            GetValue={() => {
-                                return Field.toKeyValueString(props.Document, props.fieldKey);
-                            }}
+                            GetValue={() => Field.toKeyValueString(props.Document, props.fieldKey)}
                             SetValue={(value: string) =>
-                                KeyValueBox.SetField(props.Document, props.fieldKey, value)}>
-                        </EditableView>
+                                KeyValueBox.SetField(props.Document, props.fieldKey, value)} />
                     </div>
                 </td>
             </tr>
diff --git a/src/client/views/nodes/LinkDescriptionPopup.tsx b/src/client/views/nodes/LinkDescriptionPopup.tsx
index 720af6c9d..30b272a9a 100644
--- a/src/client/views/nodes/LinkDescriptionPopup.tsx
+++ b/src/client/views/nodes/LinkDescriptionPopup.tsx
@@ -2,7 +2,6 @@ import React = require("react");
 import { observer } from "mobx-react";
 import "./LinkDescriptionPopup.scss";
 import { observable, action } from "mobx";
-import { EditableView } from "../EditableView";
 import { LinkManager } from "../../util/LinkManager";
 import { TaskCompletionBox } from "./TaskCompletedBox";
 
diff --git a/src/debug/Viewer.tsx b/src/debug/Viewer.tsx
index bebd71dcf..ee7dd1fc1 100644
--- a/src/debug/Viewer.tsx
+++ b/src/debug/Viewer.tsx
@@ -138,8 +138,7 @@ class DebugViewer extends React.Component<{ field: FieldResult, setValue(value:
             return <p>Unrecognized field type</p>;
         }
 
-        return <EditableView GetValue={() => Field.toScriptString(field)} SetValue={this.props.setValue}
-            contents={content}></EditableView>;
+        return <EditableView GetValue={() => Field.toScriptString(field)} SetValue={this.props.setValue} contents={content} />;
     }
 }
 
-- 
cgit v1.2.3-70-g09d2


From 58adadeaaf97c57a15d42fea86e75180fc3b2c14 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 24 Feb 2021 12:24:25 -0500
Subject: fixed layerProviders for treeViews to return true.  fixed sidebar
 annotations for text to add/remove from correct field.

---
 src/client/views/DocComponent.tsx                         | 14 +++++++-------
 src/client/views/collections/CollectionTreeView.tsx       |  2 +-
 src/client/views/collections/TreeView.tsx                 | 11 +++++++----
 src/client/views/nodes/formattedText/FormattedTextBox.tsx | 12 +++++++-----
 4 files changed, 22 insertions(+), 17 deletions(-)

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

diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index b800ba777..ef1228976 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -156,15 +156,15 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
         // if the moved document is already in this overlay collection nothing needs to be done.
         // otherwise, if the document can be removed from where it was, it will then be added to this document's overlay collection. 
         @action.bound
-        moveDocument(doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean): boolean {
-            return Doc.AreProtosEqual(this.props.Document, targetCollection) ? true : this.removeDocument(doc) ? addDocument(doc) : false;
+        moveDocument(doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean, annotationKey?: string): boolean {
+            return Doc.AreProtosEqual(this.props.Document, targetCollection) ? true : this.removeDocument(doc, annotationKey) ? addDocument(doc) : false;
         }
         @action.bound
-        addDocument(doc: Doc | Doc[]): boolean {
+        addDocument(doc: Doc | Doc[], annotationKey?: string): boolean {
             const docs = doc instanceof Doc ? [doc] : doc;
             docs.map(doc => doc.context = Doc.GetProto(doc).annotationOn = this.props.Document);
             const targetDataDoc = this.props.Document[DataSym];
-            const docList = DocListCast(targetDataDoc[this.annotationKey]);
+            const docList = DocListCast(targetDataDoc[annotationKey ?? this.annotationKey]);
             const added = docs.filter(d => !docList.includes(d));
             const effectiveAcl = GetEffectiveAcl(this.dataDoc);
 
@@ -184,12 +184,12 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
                     }
 
                     if (effectiveAcl === AclAddonly) {
-                        added.map(doc => Doc.AddDocToList(targetDataDoc, this.annotationKey, doc));
+                        added.map(doc => Doc.AddDocToList(targetDataDoc, annotationKey ?? this.annotationKey, doc));
                     }
                     else {
                         added.map(doc => doc.context = this.props.Document);
-                        (targetDataDoc[this.annotationKey] as List<Doc>).push(...added);
-                        targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now()));
+                        (targetDataDoc[annotationKey ?? this.annotationKey] as List<Doc>).push(...added);
+                        targetDataDoc[(annotationKey ?? this.annotationKey) + "-lastModified"] = new DateField(new Date(Date.now()));
                     }
                 }
             }
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index a12de0320..146b3cd37 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -205,7 +205,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
         const addDoc = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => this.addDoc(doc, relativeTo, before);
         const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this.props.moveDocument?.(d, target, addDoc) || false;
         return TreeView.GetChildElements(this.treeChildren, this, this.doc, this.props.DataDoc, this.props.fieldKey, this.props.ContainingCollectionDoc, undefined, addDoc, this.remove,
-            moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.styleProvider, this.props.ScreenToLocalTransform,
+            moveDoc, dropAction, this.props.addDocTab, this.props.pinToPres, this.props.styleProvider, returnTrue, this.props.ScreenToLocalTransform,
             this.outerXf, this.active, this.panelWidth, this.props.renderDepth, () => this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields),
             BoolCast(this.doc.treeViewPreventOpen), [], this.props.onCheckedClick,
             this.onChildClick, this.props.treeViewSkipFields, true, this.whenActiveChanged, this.props.dontRegisterView || Cast(this.props.Document.dontRegisterChildViews, "boolean", null), this);
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 297796b4b..dbd05f37a 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -52,6 +52,7 @@ export interface TreeViewProps {
     ScreenToLocalTransform: () => Transform;
     dontRegisterView?: boolean;
     styleProvider?: StyleProviderFunc | undefined;
+    layerProvider?: undefined | ((doc: Doc, assign?: boolean) => boolean);
     outerXf: () => { translateX: number, translateY: number };
     treeView: CollectionTreeView;
     parentKey: string;
@@ -327,7 +328,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true);
                 contentElement = TreeView.GetChildElements(contents instanceof Doc ? [contents] : DocListCast(contents),
                     this.props.treeView, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move,
-                    this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.titleStyleProvider, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active,
+                    this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.titleStyleProvider, this.props.layerProvider, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active,
                     this.props.panelWidth, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen,
                     [...this.props.renderedIds, doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.skipFields, false, this.props.whenActiveChanged, this.props.dontRegisterView, this);
             } else {
@@ -410,7 +411,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 {!docs ? (null) :
                     TreeView.GetChildElements(docs, this.props.treeView, this.layoutDoc,
                         this.dataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move,
-                        StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.props.pinToPres, this.titleStyleProvider, this.props.ScreenToLocalTransform,
+                        StrCast(this.doc.childDropAction, this.props.dropAction) as dropActionType, this.props.addDocTab, this.props.pinToPres, this.titleStyleProvider, this.props.layerProvider, this.props.ScreenToLocalTransform,
                         this.props.outerXf, this.props.active, this.props.panelWidth, this.props.renderDepth, this.props.treeViewHideHeaderFields, this.props.treeViewPreventOpen,
                         [...this.props.renderedIds, this.doc[Id]], this.props.onCheckedClick, this.props.onChildClick, this.props.skipFields, false, this.props.whenActiveChanged, this.props.dontRegisterView, this)}
             </ul >;
@@ -578,7 +579,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 DataDoc={undefined}
                 scriptContext={this}
                 styleProvider={this.titleStyleProvider}
-                layerProvider={undefined}
+                layerProvider={this.props.layerProvider}
                 docViewPath={returnEmptyDoclist}
                 treeViewDoc={this.props.treeView.props.Document}
                 addDocument={undefined}
@@ -671,7 +672,7 @@ export class TreeView extends React.Component<TreeViewProps> {
             renderDepth={this.props.renderDepth + 1}
             rootSelected={returnTrue}
             styleProvider={asText ? this.titleStyleProvider : this.embeddedStyleProvider}
-            layerProvider={undefined}
+            layerProvider={this.props.layerProvider}
             docViewPath={this.props.treeView.props.docViewPath}
             docFilters={returnEmptyFilter}
             docRangeFilters={returnEmptyFilter}
@@ -775,6 +776,7 @@ export class TreeView extends React.Component<TreeViewProps> {
         addDocTab: (doc: Doc, where: string) => boolean,
         pinToPres: (document: Doc) => void,
         styleProvider: undefined | StyleProviderFunc,
+        layerProvider: undefined | ((doc: Doc, assign?: boolean) => boolean),
         screenToLocalXf: () => Transform,
         outerXf: () => { translateX: number, translateY: number },
         active: (outsideReaction?: boolean) => boolean,
@@ -838,6 +840,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 removeDoc={StrCast(containingCollection.freezeChildren).includes("remove") ? undefined : remove}
                 addDocument={addDocument}
                 styleProvider={styleProvider}
+                layerProvider={layerProvider}
                 panelWidth={rowWidth}
                 panelHeight={rowHeight}
                 dontRegisterView={dontRegisterView}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index ce54bf57f..b4fbda9f4 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -105,7 +105,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
     private _disposers: { [name: string]: IReactionDisposer } = {};
     private _dropDisposer?: DragManager.DragDropDisposer;
     private _recordingStart: number = 0;
-    private _pause: boolean = false;
     private _ignoreScroll = false;
 
     @computed get _recording() { return this.dataDoc?.audioState === "recording"; }
@@ -1649,6 +1648,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
 
     sidebarContentScaling = () => (this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1);
     fitToBox = () => this.props.Document._fitToBox;
+    sidebarAddDocument = (doc: Doc | Doc[]) => this.addDocument(doc, this.SidebarKey);
+    sidebarMoveDocument = (doc: Doc | Doc[], targetCollection: Doc, addDocument: (doc: Doc | Doc[]) => boolean) => this.moveDocument(doc, targetCollection, addDocument, this.SidebarKey);
+    sidebarRemDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, this.SidebarKey);
     @computed get sidebarCollection() {
         const collectionProps: SubCollectionViewProps & collectionFreeformViewProps = {
             ...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit,
@@ -1660,16 +1662,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
             yMargin: 0,
             chromeStatus: "enabled",
             scaleField: this.SidebarKey + "-scale",
-            isAnnotationOverlay: true,
+            isAnnotationOverlay: false,
             fieldKey: this.SidebarKey,
             fitContentsToDoc: this.fitToBox,
             select: emptyFunction,
             active: this.annotationsActive,
             scaling: this.sidebarContentScaling,
             whenActiveChanged: this.whenActiveChanged,
-            removeDocument: this.removeDocument,
-            moveDocument: this.moveDocument,
-            addDocument: this.addDocument,
+            removeDocument: this.sidebarRemDocument,
+            moveDocument: this.sidebarMoveDocument,
+            addDocument: this.sidebarAddDocument,
             CollectionView: undefined,
             ScreenToLocalTransform: this.sidebarScreenToLocal,
             renderDepth: this.props.renderDepth + 1,
-- 
cgit v1.2.3-70-g09d2


From 17ee7f6f1f61a079ec79b71aebc65abfd72ec32a Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 25 Feb 2021 13:38:31 -0500
Subject: added an aliases toggle to file system

---
 src/client/util/DocumentManager.ts        | 12 +++++++++++-
 src/client/views/collections/TreeView.tsx | 11 ++++++-----
 2 files changed, 17 insertions(+), 6 deletions(-)

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

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 67e05f8d0..637e219d5 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -10,6 +10,8 @@ import { LightboxView } from '../views/LightboxView';
 import { DocumentView, ViewAdjustment } from '../views/nodes/DocumentView';
 import { Scripting } from './Scripting';
 import { CurrentUserUtils } from './CurrentUserUtils';
+import { TabDocView } from '../views/collections/TabDocView';
+import { UndoManager } from './UndoManager';
 
 export class DocumentManager {
 
@@ -219,4 +221,12 @@ export class DocumentManager {
     }
 
 }
-Scripting.addGlobal(function DocFocus(doc: any) { DocumentManager.Instance.getDocumentViews(Doc.GetProto(doc)).map(view => view.props.focus(doc, { willZoom: true })); });
\ No newline at end of file
+Scripting.addGlobal(function DocFocus(doc: any) {
+    const dv = DocumentManager.Instance.getDocumentView(doc);
+    if (dv && dv?.props.Document === doc) dv.props.focus(doc, { willZoom: true });
+    else {
+        const context = Cast(doc.context, Doc, null);
+        CollectionDockingView.AddSplit(context || doc, "right") && context &&
+            setTimeout(() => DocumentManager.Instance.getDocumentView(Doc.GetProto(doc))?.focus(doc));
+    }
+});
\ No newline at end of file
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index dbd05f37a..ac19a3591 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -115,11 +115,11 @@ export class TreeView extends React.Component<TreeViewProps> {
     @computed get fieldKey() { TraceMobx(); const splits = StrCast(Doc.LayoutField(this.doc)).split("fieldKey={\'"); return splits.length > 1 ? splits[1].split("\'")[0] : "data"; }
     @computed get childDocs() { TraceMobx(); return this.childDocList(this.fieldKey); }
     @computed get childLinks() { return this.childDocList("links"); }
+    @computed get childAliases() { return this.childDocList("aliases"); }
     @computed get childAnnos() { return this.childDocList(this.fieldKey + "-annotations"); }
     @computed get selected() { return SelectionManager.Views().length && SelectionManager.Views()[0].props.Document === this.props.document; }
 
     childDocList(field: string) {
-        if (this.fileSysMode && !this.doc.isFolder) return [] as Doc[];
         const layout = Doc.LayoutField(this.doc) instanceof Doc ? Doc.LayoutField(this.doc) as Doc : undefined;
         return ((this.props.dataDoc ? DocListCastOrNull(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field
             (layout ? DocListCastOrNull(layout[field]) : undefined) || // else if there's a layout doc, display it's fields
@@ -376,7 +376,7 @@ export class TreeView extends React.Component<TreeViewProps> {
     @computed get renderContent() {
         TraceMobx();
         const expandKey = this.treeViewExpandedView;
-        if (["links", "annotations", this.fieldKey].includes(expandKey)) {
+        if (["links", "annotations", "aliases", this.fieldKey].includes(expandKey)) {
             const key = expandKey === "annotations" ? this.fieldKey + "-annotations" : expandKey;
             const remDoc = (doc: Doc | Doc[]) => this.remove(doc, key);
             const localAdd = (doc: Doc, addBefore?: Doc, before?: boolean) => {
@@ -395,7 +395,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 return added;
             };
             const addDoc = (doc: Doc | Doc[], addBefore?: Doc, before?: boolean) => (doc instanceof Doc ? [doc] : doc).reduce((flg, doc) => flg && localAdd(doc, addBefore, before), true);
-            const docs = expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs;
+            const docs = expandKey === "aliases" ? this.childAliases : expandKey === "links" ? this.childLinks : expandKey === "annotations" ? this.childAnnos : this.childDocs;
             const sortKey = `${this.fieldKey}-sortCriteria`;
             let downX = 0, downY = 0;
             const sortings = ["up", "down", "Z", undefined];
@@ -422,7 +422,7 @@ export class TreeView extends React.Component<TreeViewProps> {
                 </div>
             </ul>;
         }
-        return <ul>{this.renderEmbeddedDocument(false)}</ul>;
+        return <ul>{this.renderEmbeddedDocument(false)}</ul>; // "layout"
     }
 
     get onCheckedClick() { return this.doc.type === DocumentType.COL ? undefined : this.props.onCheckedClick?.() ?? ScriptCast(this.doc.onCheckedClick); }
@@ -477,7 +477,8 @@ export class TreeView extends React.Component<TreeViewProps> {
                 <span className="collectionTreeView-keyHeader" key={this.treeViewExpandedView}
                     onPointerDown={action(() => {
                         if (this.fileSysMode) {
-                            this.doc.treeViewExpandedView = this.doc.isFolder ? this.fieldKey : this.treeViewExpandedView === "layout" ? "fields" : "layout";
+                            this.doc.treeViewExpandedView = this.doc.isFolder ? this.fieldKey : this.treeViewExpandedView === "layout" ? "fields" :
+                                this.treeViewExpandedView === "fields" ? "aliases" : "layout";
                         } else if (this.treeViewOpen) {
                             this.doc.treeViewExpandedView = this.treeViewLockExpandedView ? this.doc.treeViewExpandedView :
                                 this.treeViewExpandedView === this.fieldKey ? (Doc.UserDoc().noviceMode || this.outlineMode ? "layout" : "fields") :
-- 
cgit v1.2.3-70-g09d2

