From 9526353b2eca02cb472291e28f16e578dcbb826e Mon Sep 17 00:00:00 2001
From: Andy Rickert <andrew_rickert@brown.edu>
Date: Thu, 6 Aug 2020 12:37:51 -0400
Subject: reverting:

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

(limited to 'src/client/views/MainView.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 1b2dd1c44..20d4ecf2c 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -195,7 +195,7 @@ export class MainView extends React.Component {
             let check = false;
             const icon = "icon";
             targets.forEach((thing) => {
-                if (thing.className.toString() === "collectionSchemaView-table" || (thing as any)?.dataset[icon] === "filter" || thing.className.toString() === "beta" || thing.className.toString() === "collectionSchemaView-menuOptions-wrapper") {
+                if (thing.className.toString() === "collectionSchemaView-table" || (thing as any)?.dataset[icon] === "filter" || thing.className.toString() === "beta" || thing.className.toString() === "collectionSchemaView-menuOptions-wrapper" || thing.className.toString() === "collectionSchemaView-container") {
                     check = true;
                 }
             });
-- 
cgit v1.2.3-70-g09d2


From 97a677d363d4a45bf16f873bec6f6982103b083e Mon Sep 17 00:00:00 2001
From: Andy Rickert <andrew_rickert@brown.edu>
Date: Fri, 7 Aug 2020 18:57:22 -0400
Subject: bugfixing

---
 src/client/documents/Documents.ts   | 20 +++++++++++++---
 src/client/util/CurrentUserUtils.ts | 47 ++++++++++++++++++++++++-------------
 src/client/views/MainView.tsx       | 46 ++++++++++++++++++++++--------------
 3 files changed, 77 insertions(+), 36 deletions(-)

(limited to 'src/client/views/MainView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index b809a73b7..f5fb8c299 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -33,6 +33,7 @@ import { ColorBox } from "../views/nodes/ColorBox";
 import { ComparisonBox } from "../views/nodes/ComparisonBox";
 import { DocHolderBox } from "../views/nodes/DocHolderBox";
 import { FontIconBox } from "../views/nodes/FontIconBox";
+import { MenuIconBox } from "../views/nodes/MenuIconBox";
 import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox";
 import { ImageBox } from "../views/nodes/ImageBox";
 import { KeyValueBox } from "../views/nodes/KeyValueBox";
@@ -128,6 +129,7 @@ export interface DocumentOptions {
     isLinkButton?: boolean;
     _columnWidth?: number;
     _fontSize?: string;
+    _fontWeight?: number;
     _fontFamily?: string;
     curPage?: number;
     currentTimecode?: number; // the current timecode of a time-based document (e.g., current time of a video)  value is in seconds
@@ -135,6 +137,12 @@ export interface DocumentOptions {
     currentFrame?: number; // the current frame of a frame-based collection (e.g., progressive slide)
     lastFrame?: number; // the last frame of a frame-based collection (e.g., progressive slide)
     activeFrame?: number; // the active frame of a document in a frame base collection
+    appearFrame?: number; // the frame in which the document appears
+    presTransition?: number; //the time taken for the transition TO a document
+    presDuration?: number; //the duration of the slide in presentation view
+    presProgressivize?: boolean;
+    // xArray?: number[];
+    // yArray?: number[];
     borderRounding?: string;
     boxShadow?: string;
     dontRegisterChildViews?: boolean;
@@ -191,6 +199,10 @@ export interface DocumentOptions {
     syntaxColor?: string; // can be applied to text for syntax highlighting all matches in the text
     searchQuery?: string; // for quersyBox
     linearViewIsExpanded?: boolean; // is linear view expanded
+    isLabel?: boolean;         // whether the document is a label or not (video / audio)
+    useLinkSmallAnchor?: boolean;  // whether links to this document should use a miniature linkAnchorBox
+    audioStart?: number;       // the time frame where the audio should begin playing
+    audioEnd?: number;         // the time frame where the audio should stop playing  
     border?: string; //for searchbox
     hovercolor?: string;
 }
@@ -557,6 +569,7 @@ export namespace Docs {
             // without this, if a doc has no annotations but the user has AddOnly privileges, they won't be able to add an annotation because they would have needed to create the field's list which they don't have permissions to do.
 
             dataDoc[fieldKey + "-annotations"] = new List<Doc>();
+            dataDoc.aliases = new List<Doc>();
 
             proto.links = ComputedField.MakeFunction("links(self)");
 
@@ -625,7 +638,7 @@ export namespace Docs {
         }
 
         export function AudioDocument(url: string, options: DocumentOptions = {}) {
-            const instance = InstanceFromProto(Prototypes.get(DocumentType.AUDIO), new AudioField(new URL(url)), options);
+            const instance = InstanceFromProto(Prototypes.get(DocumentType.AUDIO), new AudioField(new URL(url)), { useLinkSmallAnchor: true, ...options }); // hideLinkButton: false, useLinkSmallAnchor: false,
             Doc.GetProto(instance).backgroundColor = ComputedField.MakeFunction("this._audioState === 'playing' ? 'green':'gray'");
             return instance;
         }
@@ -919,6 +932,8 @@ export namespace DocUtils {
         if (target.doc === Doc.UserDoc()) return undefined;
 
         const linkDoc = Docs.Create.LinkDocument(source, target, { linkRelationship, layoutKey: "layout_linkView", description }, id);
+        Doc.GetProto(linkDoc)["anchor1-useLinkSmallAnchor"] = source.doc.useLinkSmallAnchor;
+        Doc.GetProto(linkDoc)["anchor2-useLinkSmallAnchor"] = target.doc.useLinkSmallAnchor;
         linkDoc.linkDisplay = true;
         linkDoc.hidden = true;
         linkDoc.layout_linkView = Cast(Cast(Doc.UserDoc()["template-button-link"], Doc, null).dragFactory, Doc, null);
@@ -1185,5 +1200,4 @@ export namespace DocUtils {
 }
 
 Scripting.addGlobal("Docs", Docs);
-Scripting.addGlobal(function makeDelegate(proto: any) { const d = Docs.Create.DelegateDocument(proto, { title: "child of " + proto.title }); return d; });
-
+Scripting.addGlobal(function makeDelegate(proto: any) { const d = Docs.Create.DelegateDocument(proto, { title: "child of " + proto.title }); return d; });
\ No newline at end of file
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 53d187aa0..38573c1ea 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -8,7 +8,7 @@ import { Doc, DocListCast, DocListCastAsync, DataSym } from "../../fields/Doc";
 import { List } from "../../fields/List";
 import { listSpec } from "../../fields/Schema";
 import { ScriptField, ComputedField } from "../../fields/ScriptField";
-import { Cast, PromiseValue, StrCast, NumCast } from "../../fields/Types";
+import { Cast, PromiseValue, StrCast, NumCast, BoolCast } from "../../fields/Types";
 import { nullAudio } from "../../fields/URLField";
 import { DragManager } from "./DragManager";
 import { Scripting } from "./Scripting";
@@ -248,8 +248,8 @@ export class CurrentUserUtils {
         if (doc["template-buttons"] === undefined) {
             doc["template-buttons"] = new PrefetchProxy(Docs.Create.MasonryDocument(requiredTypes, {
                 title: "Advanced Item Prototypes", _xMargin: 0, _showTitle: "title",
-                hidden: ComputedField.MakeFunction("self.target.noviceMode") as any,
-                target: doc,
+                hidden: ComputedField.MakeFunction("self.userDoc.noviceMode") as any,
+                userDoc: doc,
                 _autoHeight: true, _width: 500, _columnWidth: 35, ignoreClick: true, lockedPosition: true, _chromeStatus: "disabled",
                 dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
             }));
@@ -387,7 +387,7 @@ export class CurrentUserUtils {
 
     static creatorBtnDescriptors(doc: Doc): {
         title: string, toolTip: string, icon: string, drag?: string, ignoreClick?: boolean,
-        click?: string, ischecked?: string, activeInkPen?: Doc, backgroundColor?: string, dragFactory?: Doc
+        click?: string, ischecked?: string, activeInkPen?: Doc, backgroundColor?: string, dragFactory?: Doc, noviceMode?: boolean
     }[] {
         if (doc.emptyPresentation === undefined) {
             doc.emptyPresentation = Docs.Create.PresDocument(new List<Doc>(),
@@ -421,22 +421,22 @@ export class CurrentUserUtils {
                 { _width: 250, _height: 250, title: "container" });
         }
         if (doc.emptyWebpage === undefined) {
-            doc.emptyWebpage = Docs.Create.WebDocument("", { title: "webpage", _nativeWidth: 850, _nativeHeight: 962, _width: 600, UseCors: true });
+            doc.emptyWebpage = Docs.Create.WebDocument("", { title: "webpage", _nativeWidth: 850, _nativeHeight: 962, _width: 400, UseCors: true });
         }
         if (doc.activeMobileMenu === undefined) {
             this.setupActiveMobileMenu(doc);
         }
         return [
-            { toolTip: "Drag a collection", title: "Col", icon: "folder", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyCollection as Doc },
-            { toolTip: "Drag a web page", title: "Web", icon: "globe-asia", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyWebpage as Doc },
+            { toolTip: "Drag a collection", title: "Col", icon: "folder", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyCollection as Doc, noviceMode: true },
+            { toolTip: "Drag a web page", title: "Web", icon: "globe-asia", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyWebpage as Doc, noviceMode: true },
             { toolTip: "Drag a cat image", title: "Image", icon: "cat", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyImage as Doc },
-            { toolTip: "Drag a comparison box", title: "Compare", icon: "columns", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyComparison as Doc },
+            { toolTip: "Drag a comparison box", title: "Compare", icon: "columns", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyComparison as Doc, noviceMode: true },
             { toolTip: "Drag a screengrabber", title: "Grab", icon: "photo-video", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyScreenshot as Doc },
             //  { title: "Drag a webcam", title: "Cam", icon: "video", ignoreClick: true, drag: 'Docs.Create.WebCamDocument("", { _width: 400, _height: 400, title: "a test cam" })' },
-            { toolTip: "Drag a audio recorder", title: "Audio", icon: "microphone", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyAudio as Doc },
-            { toolTip: "Drag a button", title: "Button", icon: "bolt", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyButton as Doc },
+            { toolTip: "Drag a audio recorder", title: "Audio", icon: "microphone", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyAudio as Doc, noviceMode: true },
+            { toolTip: "Drag a button", title: "Button", icon: "bolt", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyButton as Doc, noviceMode: true },
 
-            { toolTip: "Drag a presentation view", title: "Prezi", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true)`, dragFactory: doc.emptyPresentation as Doc },
+            { toolTip: "Drag a presentation view", title: "Prezi", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true)`, dragFactory: doc.emptyPresentation as Doc, noviceMode: true },
             { toolTip: "Drag a search box", title: "Query", icon: "search", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptySearch as Doc },
             { toolTip: "Drag a scripting box", title: "Script", icon: "terminal", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyScript as Doc },
             // { title: "Drag an import folder", title: "Load", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' },
@@ -465,7 +465,7 @@ export class CurrentUserUtils {
             }
         }
         const buttons = CurrentUserUtils.creatorBtnDescriptors(doc).filter(d => !alreadyCreatedButtons?.includes(d.title));
-        const creatorBtns = buttons.map(({ title, toolTip, icon, ignoreClick, drag, click, ischecked, activeInkPen, backgroundColor, dragFactory }) => Docs.Create.FontIconDocument({
+        const creatorBtns = buttons.map(({ title, toolTip, icon, ignoreClick, drag, click, ischecked, activeInkPen, backgroundColor, dragFactory, noviceMode }) => Docs.Create.FontIconDocument({
             _nativeWidth: 50, _nativeHeight: 50, _width: 50, _height: 50,
             icon,
             title,
@@ -479,6 +479,8 @@ export class CurrentUserUtils {
             backgroundColor,
             removeDropProperties: new List<string>(["dropAction"]),
             dragFactory,
+            userDoc: noviceMode ? undefined as any : doc,
+            hidden: noviceMode ? undefined as any : ComputedField.MakeFunction("self.userDoc.noviceMode")
         }));
 
         if (dragCreatorSet === undefined) {
@@ -532,8 +534,8 @@ export class CurrentUserUtils {
                     onClick: ScriptField.MakeScript(click, { scriptContext: "any" }),
                 }));
             const userDoc = menuBtns[menuBtns.length - 1];
-            userDoc.target = doc;
-            userDoc.hidden = ComputedField.MakeFunction("self.target.noviceMode");
+            userDoc.userDoc = doc;
+            userDoc.hidden = ComputedField.MakeFunction("self.userDoc.noviceMode");
 
             doc.menuStack = new PrefetchProxy(Docs.Create.StackingDocument(menuBtns, {
                 title: "menuItemPanel",
@@ -769,8 +771,19 @@ export class CurrentUserUtils {
         }
     }
 
+    static setupSidebarContainer(doc: Doc) {
+        if (doc.sidebar === undefined) {
+            const sidebarContainer = new Doc();
+            sidebarContainer._chromeStatus = "disabled";
+            sidebarContainer.onClick = ScriptField.MakeScript("freezeSidebar()");
+            doc.sidebar = new PrefetchProxy(sidebarContainer);
+        }
+        return doc.sidebar as Doc;
+    }
+
     // setup the list of sidebar mode buttons which determine what is displayed in the sidebar
     static async setupSidebarButtons(doc: Doc) {
+        CurrentUserUtils.setupSidebarContainer(doc);
         await CurrentUserUtils.setupToolsBtnPanel(doc);
         CurrentUserUtils.setupWorkspaces(doc);
         CurrentUserUtils.setupCatalog(doc);
@@ -825,7 +838,7 @@ export class CurrentUserUtils {
     // Right sidebar is where mobile uploads are contained
     static setupSharingSidebar(doc: Doc) {
         if (doc["sidebar-sharing"] === undefined) {
-            doc["sidebar-sharing"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Sharing Sidebar" }));
+            doc["sidebar-sharing"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Shared Documents", childDropAction: "alias" }));
         }
     }
 
@@ -891,6 +904,8 @@ export class CurrentUserUtils {
         doc.fontFamily = StrCast(doc.fontFamily, "Arial");
         doc.fontColor = StrCast(doc.fontColor, "black");
         doc.fontHighlight = StrCast(doc.fontHighlight, "");
+        doc.defaultColor = StrCast(doc.defaultColor, "white");
+        doc.noviceMode = BoolCast(doc.noviceMode, true);
         doc["constants-snapThreshold"] = NumCast(doc["constants-snapThreshold"], 10); //
         doc["constants-dragThreshold"] = NumCast(doc["constants-dragThreshold"], 4); //
         Utils.DRAG_THRESHOLD = NumCast(doc["constants-dragThreshold"]);
@@ -945,4 +960,4 @@ Scripting.addGlobal(function createNewWorkspace() { return MainView.Instance.cre
 Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); },
     "returns all the links to the document or its annotations", "(doc: any)");
 Scripting.addGlobal(function directLinks(doc: any) { return new List(LinkManager.Instance.getAllDirectLinks(doc)); },
-    "returns all the links directly to the document", "(doc: any)");
+    "returns all the links directly to the document", "(doc: any)");
\ No newline at end of file
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 20d4ecf2c..eb9f77641 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -82,8 +82,7 @@ export class MainView extends React.Component {
     @computed public get mainFreeform(): Opt<Doc> { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); }
     @computed public get searchDoc() { return Cast(this.userDoc["search-panel"], Doc) as Doc; }
 
-    sidebar: string = "sidebar";
-    @observable public sidebarContent: any = this.userDoc?.[this.sidebar];
+    @observable public sidebarContent: any = this.userDoc?.sidebar;
     @observable public panelContent: string = "none";
     @observable public showProperties: boolean = false;
     public isPointerDown = false;
@@ -176,7 +175,8 @@ export class MainView extends React.Component {
             fa.faFillDrip, fa.faLink, fa.faUnlink, fa.faBold, fa.faItalic, fa.faChevronLeft, fa.faUnderline, fa.faStrikethrough, fa.faSuperscript, fa.faSubscript,
             fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper,
             fa.faDesktop, fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle,
-            fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer, fa.faExpand, fa.faUndo, fa.faSlidersH, fa.faAngleDoubleLeft);
+            fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer, fa.faExpand, fa.faUndo, fa.faSlidersH, fa.faAngleDoubleLeft, fa.faAngleUp,
+            fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, faBuffer);
         this.initEventListeners();
         this.initAuthenticationRouters();
     }
@@ -195,7 +195,7 @@ export class MainView extends React.Component {
             let check = false;
             const icon = "icon";
             targets.forEach((thing) => {
-                if (thing.className.toString() === "collectionSchemaView-table" || (thing as any)?.dataset[icon] === "filter" || thing.className.toString() === "beta" || thing.className.toString() === "collectionSchemaView-menuOptions-wrapper" || thing.className.toString() === "collectionSchemaView-container") {
+                if (thing.className.toString() === "collectionSchemaView-table" || (thing as any)?.dataset[icon] === "filter" || thing.className.toString() === "beta" || thing.className.toString() === "collectionSchemaView-menuOptions-wrapper") {
                     check = true;
                 }
             });
@@ -330,6 +330,16 @@ export class MainView extends React.Component {
 
     defaultBackgroundColors = (doc: Opt<Doc>) => {
         if (this.panelContent === doc?.title) return "lightgrey";
+
+        if (doc?.type === DocumentType.COL) {
+            if (doc.title === "Basic Item Creators" || doc.title === "sidebar-tools"
+                || doc.title === "sidebar-recentlyClosed" || doc.title === "sidebar-catalog"
+                || doc.title === "Mobile Uploads" || doc.title === "COLLECTION_PROTO"
+                || doc.title === "Advanced Item Prototypes" || doc.title === "all Creators") {
+                return "lightgrey";
+            }
+            return StrCast(Doc.UserDoc().defaultColor);
+        }
         if (this.darkScheme) {
             switch (doc?.type) {
                 case DocumentType.FONTICON: return "white";
@@ -388,7 +398,7 @@ export class MainView extends React.Component {
         TraceMobx();
         const mainContainer = this.mainContainer;
         const width = this.flyoutWidth + this.propertiesWidth();
-        return <div className="mainContent-div" onDrop={this.onDrop} style={{ width: `calc(100% - ${width}px)` }}>
+        return <div className="mainContent-div" onDrop={this.onDrop} style={{ width: `calc(100% - ${width}px)`, height: `calc(100% - 32px)` }}>
             {!mainContainer ? (null) : this.mainDocView}
         </div>;
     }
@@ -427,17 +437,17 @@ export class MainView extends React.Component {
     }
     sidebarScreenToLocal = () => new Transform(0, (CollectionMenu.Instance.Pinned ? -35 : 0), 1);
     //sidebarScreenToLocal = () => new Transform(0, (RichTextMenu.Instance.Pinned ? -35 : 0) + (CollectionMenu.Instance.Pinned ? -35 : 0), 1);
-    mainContainerXf = () => this.sidebarScreenToLocal().translate(0, -this._buttonBarHeight);
+    mainContainerXf = () => this.sidebarScreenToLocal().translate(-55, 0);
 
     @computed get closePosition() { return 55 + this.flyoutWidth; }
     @computed get flyout() {
         if (!this.sidebarContent) return null;
         return <div className="mainView-libraryFlyout">
-            <div className="mainView-contentArea" style={{ position: "relative", height: `100%`, width: "100%", overflow: "visible" }}>
-                {this.flyoutWidth > 0 ? <div className="mainView-libraryFlyout-close"
+            <div className="mainView-contentArea" style={{ position: "relative", height: `calc(100% - 32px)`, width: "100%", overflow: "visible" }}>
+                {/* {this.flyoutWidth > 0 ? <div className="mainView-libraryFlyout-close"
                     onPointerDown={this.closeFlyout}>
                     <FontAwesomeIcon icon="times" color="black" size="lg" />
-                </div> : null}
+                </div> : null} */}
 
                 <DocumentView
                     Document={this.sidebarContent}
@@ -465,6 +475,7 @@ export class MainView extends React.Component {
                     ContainingCollectionView={undefined}
                     ContainingCollectionDoc={undefined}
                     relative={true}
+                    forcedBackgroundColor={() => "lightgrey"}
                 />
             </div>
             {this.docButtons}</div>;
@@ -504,7 +515,7 @@ export class MainView extends React.Component {
     }
 
 
-    @action @undoBatch
+    @action
     closeFlyout = () => {
         this._lastButton && (this._lastButton.color = "white");
         this._lastButton && (this._lastButton._backgroundColor = "");
@@ -515,7 +526,7 @@ export class MainView extends React.Component {
     get groupManager() { return GroupManager.Instance; }
 
     _lastButton: Doc | undefined;
-    @action @undoBatch
+    @action
     selectMenu = (button: Doc, str: string) => {
         this._lastButton && (this._lastButton.color = "white");
         this._lastButton && (this._lastButton._backgroundColor = "");
@@ -544,7 +555,7 @@ export class MainView extends React.Component {
         return true;
     }
 
-    @action @undoBatch
+    @action
     closeProperties = () => {
         CurrentUserUtils.propertiesWidth = 0;
     }
@@ -572,7 +583,8 @@ export class MainView extends React.Component {
                 <div className="mainView-flyoutContainer" style={{ width: this.flyoutWidth }}>
                     {this.flyoutWidth !== 0 ? <div className="mainView-libraryHandle"
                         onPointerDown={this.onFlyoutPointerDown}
-                        style={{ backgroundColor: 'lightgrey' }}>
+                    //style={{ backgroundColor: '#8c8b8b' }}
+                    >
                         <span title="library View Dragger" style={{
                             width: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "3vw",
                             //height: (this.flyoutWidth !== 0 && this._flyoutTranslate) ? "100%" : "100vh",
@@ -599,11 +611,11 @@ export class MainView extends React.Component {
                     <div className="mainView-propertiesDragger" title="Properties View Dragger" onPointerDown={this.onPropertiesPointerDown}
                         style={{ right: rightFlyout, top: "50%" }}>
                         <div className="mainView-propertiesDragger-icon">
-                            <FontAwesomeIcon icon={this.propertiesIcon} color="white" size="sm" /> </div>
+                            <FontAwesomeIcon icon={this.propertiesIcon} color="black" size="sm" /> </div>
                     </div>
                 }
                 {this.propertiesWidth() < 10 ? (null) :
-                    <div style={{ width: this.propertiesWidth() }}> {this.propertiesView} </div>}
+                    <div style={{ width: this.propertiesWidth(), height: "calc(100% - 35px)" }}> {this.propertiesView} </div>}
             </div>
         </>;
     }
@@ -776,7 +788,7 @@ export class MainView extends React.Component {
             <FormatShapePane />
             <div style={{ display: "none" }}><RichTextMenu key="rich" /></div>
             {LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
-            {DocumentLinksButton.EditLink ? <LinkMenu location={DocumentLinksButton.EditLinkLoc} docView={DocumentLinksButton.EditLink} addDocTab={DocumentLinksButton.EditLink.props.addDocTab} changeFlyout={emptyFunction} /> : (null)}
+            {DocumentLinksButton.EditLink ? <LinkMenu docView={DocumentLinksButton.EditLink} addDocTab={DocumentLinksButton.EditLink.props.addDocTab} changeFlyout={emptyFunction} /> : (null)}
             {LinkDocPreview.LinkInfo ? <LinkDocPreview location={LinkDocPreview.LinkInfo.Location} backgroundColor={this.defaultBackgroundColors}
                 linkDoc={LinkDocPreview.LinkInfo.linkDoc} linkSrc={LinkDocPreview.LinkInfo.linkSrc} href={LinkDocPreview.LinkInfo.href}
                 addDocTab={LinkDocPreview.LinkInfo.addDocTab} /> : (null)}
@@ -805,4 +817,4 @@ Scripting.addGlobal(function copyWorkspace() {
     Doc.AddDocToList(workspaces, "data", copiedWorkspace);
     // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
     setTimeout(() => MainView.Instance.openWorkspace(copiedWorkspace), 0);
-});
+});
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 3bd97210a1112d9d0af802255677caf1de95616c Mon Sep 17 00:00:00 2001
From: Andy Rickert <andrew_rickert@brown.edu>
Date: Sat, 8 Aug 2020 21:24:47 -0400
Subject: tidying up assorted features, disabling editing doc keys in search,
 etc

---
 src/client/views/DocComponent.tsx                  |   2 +
 src/client/views/GlobalKeyHandler.ts               |   2 +
 src/client/views/MainView.tsx                      |   2 +-
 .../views/collections/CollectionSchemaCells.tsx    | 173 +++++++++++++--------
 .../views/collections/CollectionSchemaHeaders.tsx  |  11 +-
 .../views/collections/CollectionSchemaView.scss    |  45 +++++-
 .../views/collections/CollectionSchemaView.tsx     |  26 +++-
 src/client/views/collections/CollectionView.tsx    |   3 +
 src/client/views/collections/SchemaTable.tsx       |   8 +-
 src/client/views/search/SearchBox.tsx              |  12 +-
 10 files changed, 199 insertions(+), 85 deletions(-)

(limited to 'src/client/views/MainView.tsx')

diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 831c246d1..75ac9141d 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -170,6 +170,8 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
                         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()));
+                        const lastModified = "lastModified";
+                        targetDataDoc[lastModified] = new DateField(new Date(Date.now()));
                     }
                 }
             }
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 3a61e89ce..3b8828ecc 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -331,6 +331,8 @@ export default class KeyManager {
                             undoBatch(() => {
                                 targetDataDoc[fieldKey] = new List<Doc>([...docList, ...added]);
                                 targetDataDoc[fieldKey + "-lastModified"] = new DateField(new Date(Date.now()));
+                                const lastModified = "lastModified";
+                                targetDataDoc[lastModified] = new DateField(new Date(Date.now()));
                             })();
                         }
                     }
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index eb9f77641..744e5c68b 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -195,7 +195,7 @@ export class MainView extends React.Component {
             let check = false;
             const icon = "icon";
             targets.forEach((thing) => {
-                if (thing.className.toString() === "collectionSchemaView-table" || (thing as any)?.dataset[icon] === "filter" || thing.className.toString() === "beta" || thing.className.toString() === "collectionSchemaView-menuOptions-wrapper") {
+                if (thing.className.toString() === "collectionSchemaView-searchContainer" || (thing as any)?.dataset[icon] === "filter" || thing.className.toString() === "collectionSchema-header-menuOptions") {
                     check = true;
                 }
             });
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 0bc2afd47..3725b0dd9 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -159,6 +159,29 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
     //     e.stopPropagation();
     // }
 
+    returnHighlights(bing: (() => string), positions?: number[]) {
+        const results = [];
+        const contents = bing();
+
+        if (positions !== undefined) {
+            StrCast(this.props.Document._searchString)
+            const length = StrCast(this.props.Document._searchString).length;
+
+            results.push(<span style={{ color: contents ? "black" : "grey" }}>{contents ? contents.slice(0, positions[0]) : "enter value"}</span>);
+            positions.forEach((num, cur) => {
+                results.push(<span style={{ backgroundColor: "#FFFF00", color: contents ? "black" : "grey" }}>{contents ? contents.slice(num, num + length) : "enter value"}</span>);
+                let end = 0;
+                cur === positions.length - 1 ? end = contents.length : end = positions[cur + 1];
+                results.push(<span style={{ color: contents ? "black" : "grey" }}>{contents ? contents.slice(num + length, end) : "enter value"}</span>);
+            }
+            );
+            return results;
+        }
+        else {
+            return <span style={{ color: contents ? "black" : "grey" }}>{contents ? contents?.valueOf() : "enter value"}</span>;
+        }
+    }
+
     renderCellWithType(type: string | undefined) {
         const dragRef: React.RefObject<HTMLDivElement> = React.createRef();
 
@@ -274,24 +297,95 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
                 positions.pop();
             }
         }
+        let search = false;
+        if (this.props.Document._searchDoc !== undefined) {
+            search = true;
+        }
+
+
         return (
             <div className="collectionSchemaView-cellContainer" style={{ cursor: fieldIsDoc ? "grab" : "auto" }}
                 ref={dragRef} onPointerDown={this.onPointerDown} onPointerEnter={onPointerEnter} onPointerLeave={onPointerLeave}>
                 <div className={className} ref={this._focusRef} onPointerDown={onItemDown} tabIndex={-1}>
                     <div className="collectionSchemaView-cellContents" ref={type === undefined || type === "document" ? this.dropRef : null} key={props.Document[Id]}>
-                        <EditableView
-                            positions={positions.length > 0 ? positions : undefined}
-                            search={StrCast(this.props.Document._searchString) ? StrCast(this.props.Document._searchString) : undefined}
-                            editing={this._isEditing}
-                            isEditingCallback={this.isEditingCallback}
-                            display={"inline"}
-                            contents={contents ? contents : type === "number" ? "0" : "undefined"}
-                            highlight={positions.length > 0 ? true : undefined}
-                            //contents={StrCast(contents)}
-                            height={"auto"}
-                            maxHeight={Number(MAX_ROW_HEIGHT)}
-                            placeholder={"enter value"}
-                            bing={() => {
+                        {!search ?
+                            <EditableView
+                                positions={positions.length > 0 ? positions : undefined}
+                                search={StrCast(this.props.Document._searchString) ? StrCast(this.props.Document._searchString) : undefined}
+                                editing={this._isEditing}
+                                isEditingCallback={this.isEditingCallback}
+                                display={"inline"}
+                                contents={contents ? contents : type === "number" ? "0" : "undefined"}
+                                highlight={positions.length > 0 ? true : undefined}
+                                //contents={StrCast(contents)}
+                                height={"auto"}
+                                maxHeight={Number(MAX_ROW_HEIGHT)}
+                                placeholder={"enter value"}
+                                bing={() => {
+                                    const cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey]));
+                                    if (cfield !== undefined) {
+                                        // if (typeof(cfield)===RichTextField)
+                                        const a = cfield as RichTextField;
+                                        if (a.Text !== undefined) {
+                                            return (a.Text);
+                                        }
+                                        else if (StrCast(cfield)) {
+                                            return StrCast(cfield);
+                                        }
+                                        else {
+                                            return String(NumCast(cfield));
+                                        }
+                                    }
+                                }}
+                                GetValue={() => {
+                                    if (type === "number" && (contents === 0 || contents === "0")) {
+                                        return "0";
+                                    } else {
+                                        const cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey]));
+                                        if (type === "number") {
+                                            return StrCast(cfield);
+                                        }
+                                        const cscript = cfield instanceof ComputedField ? cfield.script.originalScript : undefined;
+                                        const cfinalScript = cscript?.split("return")[cscript.split("return").length - 1];
+                                        const val = cscript !== undefined ? (cfinalScript?.endsWith(";") ? `:=${cfinalScript?.substring(0, cfinalScript.length - 2)}` : cfinalScript) :
+                                            Field.IsField(cfield) ? Field.toScriptString(cfield) : "";
+                                        return val;
+
+                                    }
+
+                                }}
+                                SetValue={action((value: string) => {
+                                    let retVal = false;
+
+                                    if (value.startsWith(":=")) {
+                                        retVal = this.props.setComputed(value.substring(2), props.Document, this.props.rowProps.column.id!, this.props.row, this.props.col);
+                                    } else {
+                                        const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } });
+                                        if (script.compiled) {
+                                            retVal = this.applyToDoc(props.Document, this.props.row, this.props.col, script.run);
+                                        }
+
+                                    }
+                                    if (retVal) {
+                                        this._isEditing = false; // need to set this here. otherwise, the assignment of the field will invalidate & cause render() to be called with the wrong value for 'editing'
+                                        this.props.setIsEditing(false);
+                                    }
+                                    return retVal;
+
+                                    //return true;
+                                })}
+                                OnFillDown={async (value: string) => {
+                                    const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } });
+                                    if (script.compiled) {
+                                        DocListCast(this.props.Document[this.props.fieldKey]).
+                                            forEach((doc, i) => value.startsWith(":=") ?
+                                                this.props.setComputed(value.substring(2), doc, this.props.rowProps.column.id!, i, this.props.col) :
+                                                this.applyToDoc(doc, i, this.props.col, script.run));
+                                    }
+                                }}
+                            />
+                            :
+                            this.returnHighlights(() => {
                                 const cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey]));
                                 if (cfield !== undefined) {
                                     // if (typeof(cfield)===RichTextField)
@@ -306,56 +400,11 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
                                         return String(NumCast(cfield));
                                     }
                                 }
-                            }}
-                            GetValue={() => {
-                                if (type === "number" && (contents === 0 || contents === "0")) {
-                                    return "0";
-                                } else {
-                                    const cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey]));
-                                    if (type === "number") {
-                                        return StrCast(cfield);
-                                    }
-                                    const cscript = cfield instanceof ComputedField ? cfield.script.originalScript : undefined;
-                                    const cfinalScript = cscript?.split("return")[cscript.split("return").length - 1];
-                                    const val = cscript !== undefined ? (cfinalScript?.endsWith(";") ? `:=${cfinalScript?.substring(0, cfinalScript.length - 2)}` : cfinalScript) :
-                                        Field.IsField(cfield) ? Field.toScriptString(cfield) : "";
-                                    return val;
-
+                                else {
+                                    return "";
                                 }
-
-                            }}
-                            SetValue={action((value: string) => {
-                                let retVal = false;
-
-                                if (value.startsWith(":=")) {
-                                    retVal = this.props.setComputed(value.substring(2), props.Document, this.props.rowProps.column.id!, this.props.row, this.props.col);
-                                } else {
-                                    const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } });
-                                    if (script.compiled) {
-                                        retVal = this.applyToDoc(props.Document, this.props.row, this.props.col, script.run);
-                                    }
-
-                                }
-                                if (retVal) {
-                                    this._isEditing = false; // need to set this here. otherwise, the assignment of the field will invalidate & cause render() to be called with the wrong value for 'editing'
-                                    this.props.setIsEditing(false);
-                                }
-                                return retVal;
-
-                                //return true;
-                            })}
-                            OnFillDown={async (value: string) => {
-                                const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } });
-                                if (script.compiled) {
-                                    DocListCast(this.props.Document[this.props.fieldKey]).
-                                        forEach((doc, i) => value.startsWith(":=") ?
-                                            this.props.setComputed(value.substring(2), doc, this.props.rowProps.column.id!, i, this.props.col) :
-                                            this.applyToDoc(doc, i, this.props.col, script.run));
-                                }
-                            }}
-                        />
-
-
+                            }, positions)
+                        }
                     </div >
                     {/* {fieldIsDoc ? docExpander : null} */}
                 </div>
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index 892b93f80..bde7d054e 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -330,7 +330,9 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
     @undoBatch
     onKeyDown = (e: React.KeyboardEvent): void => {
         if (e.key === "Enter") {
-            const keyOptions = this._searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
+            let keyOptions = this._searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
+            let blockedkeys = ["proto", "x", "y", "_width", "_height", "_autoHeight", "_fontSize", "_fontFamily", "context", "zIndex", "_timeStampOnEnter", "lines", "highlighting", "searchMatch", "creationDate", "isPrototype", "text-annotations", "aliases", "text-lastModified", "text-noTemplate", "layoutKey", "baseProto", "_xMargin", "_yMargin", "layout", "layout_keyValue", "links"];
+            keyOptions = keyOptions.filter(n => !blockedkeys.includes(n));
             if (keyOptions.length) {
                 this.onSelect(keyOptions[0]);
             } else if (this._searchTerm !== "" && this.props.canAddNew) {
@@ -375,10 +377,13 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
         }
         const searchTerm = this._searchTerm.trim() === "New field" ? "" : this._searchTerm;
 
-        const keyOptions = searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
+        let keyOptions = searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1);
         const exactFound = keyOptions.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1 ||
             this.props.existingKeys.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1;
 
+        let blockedkeys = ["proto", "x", "y", "_width", "_height", "_autoHeight", "_fontSize", "_fontFamily", "context", "zIndex", "_timeStampOnEnter", "lines", "highlighting", "searchMatch", "creationDate", "isPrototype", "text-annotations", "aliases", "text-lastModified", "text-noTemplate", "layoutKey", "baseProto", "_xMargin", "_yMargin", "layout", "layout_keyValue", "links"];
+        keyOptions = keyOptions.filter(n => !blockedkeys.includes(n));
+
         const options = keyOptions.map(key => {
             return <div key={key} className="key-option" style={{
                 border: "1px solid lightgray",
@@ -418,7 +423,7 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
             this.defaultMenuHeight = 0;
             return <></>;
         }
-        const keyOptions: string[] = [];
+        let keyOptions: string[] = [];
         const colpos = this._searchTerm.indexOf(":");
         const temp = this._searchTerm.slice(colpos + 1, this._searchTerm.length);
         this.props.docs?.forEach((doc) => {
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 0d09f2031..86bf9d0e0 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -43,6 +43,49 @@
     // }
 }
 
+.collectionSchemaView-searchContainer {
+    border-width: $COLLECTION_BORDER_WIDTH;
+    border-color: $intermediate-color;
+    border-style: solid;
+    border-radius: $border-radius;
+    box-sizing: border-box;
+    position: relative;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    margin-top: 0;
+    transition: top 0.5s;
+    display: flex;
+    justify-content: space-between;
+    flex-wrap: nowrap;
+    touch-action: none;
+
+    div {
+        touch-action: none;
+    }
+
+
+    .collectionSchemaView-tableContainer {
+        width: 100%;
+        height: 100%;
+    }
+
+    .collectionSchemaView-dividerDragger {
+        position: relative;
+        height: 100%;
+        width: 20px;
+        z-index: 20;
+        right: 0;
+        top: 0;
+        background: gray;
+        cursor: col-resize;
+    }
+
+    // .documentView-node:first-child {
+    //     background: $light-color;
+    // }
+}
+
 .ReactTable {
     width: 100%;
     background: white;
@@ -165,7 +208,7 @@
 
 
 .collectionSchema-header-menu {
-    height: 100%;
+    height: auto;
     z-index: 100;
     position: absolute;
     background:white;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index a003de0d3..7409640eb 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -11,7 +11,7 @@ import { Doc } from "../../../fields/Doc";
 import { List } from "../../../fields/List";
 import { listSpec } from "../../../fields/Schema";
 import { PastelSchemaPalette, SchemaHeaderField } from "../../../fields/SchemaHeaderField";
-import { Cast, NumCast } from "../../../fields/Types";
+import { Cast, NumCast, BoolCast } from "../../../fields/Types";
 import { TraceMobx } from "../../../fields/util";
 import { emptyFunction, returnFalse, returnOne, returnZero, setupMoveUpEvents } from "../../../Utils";
 import { SnappingManager } from "../../util/SnappingManager";
@@ -71,8 +71,18 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     @observable _pointerY = 0;
     @observable _openTypes: boolean = false;
     @computed get menuCoordinates() {
-        const x = Math.max(0, Math.min(document.body.clientWidth - this._menuWidth, this._pointerX));
-        const y = Math.max(0, Math.min(document.body.clientHeight - this._menuHeight, this._pointerY));
+        let searchx = 0;
+        let searchy = 0;
+        if (this.props.Document._searchDoc !== undefined) {
+            let el = document.getElementsByClassName("collectionSchemaView-searchContainer")[0];
+            if (el !== undefined) {
+                let rect = el.getBoundingClientRect();
+                searchx = rect.x;
+                searchy = rect.y
+            }
+        }
+        const x = Math.max(0, Math.min(document.body.clientWidth - this._menuWidth, this._pointerX)) - searchx;
+        const y = Math.max(0, Math.min(document.body.clientHeight - this._menuHeight, this._pointerY)) - searchy;
         return this.props.ScreenToLocalTransform().transformPoint(x, y);
     }
 
@@ -611,14 +621,18 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
     onKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
     }
     render() {
+        let name = "collectionSchemaView-container";
+        if (this.props.Document._searchDoc !== undefined) {
+            name = "collectionSchemaView-searchContainer";
+        }
         TraceMobx();
         const menuContent = this.renderMenuContent;
         const menu = <div className="collectionSchema-header-menu" ref={this.setNode}
             onWheel={e => this.onZoomMenu(e)}
             onPointerDown={e => this.onHeaderClick(e)}
             style={{
-                position: "fixed", background: "white",
-                transform: `translate(${this.menuCoordinates[0] / this.scale}px, ${this.menuCoordinates[1] / this.scale}px)`
+                position: "fixed", background: "white", border: "black 1px solid",
+                transform: `translate(${(this.menuCoordinates[0] / this.scale)}px, ${(this.menuCoordinates[1] / this.scale)}px)`
             }}>
             <Measure offset onResize={action((r: any) => {
                 const dim = this.props.ScreenToLocalTransform().inverse().transformDirection(r.offset.width, r.offset.height);
@@ -627,7 +641,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
                 {({ measureRef }) => <div ref={measureRef}> {menuContent} </div>}
             </Measure>
         </div>;
-        return <div className="collectionSchemaView-container"
+        return <div className={name}
             style={{
                 overflow: this.props.overflow === true ? "auto" : undefined,
                 pointerEvents: !this.props.active() && !SnappingManager.GetIsDragging() ? "none" : undefined,
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 4d1cb670c..30747ff4f 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -46,6 +46,7 @@ import { CollectionTimeView } from './CollectionTimeView';
 import { CollectionTreeView } from "./CollectionTreeView";
 import './CollectionView.scss';
 import { ContextMenuProps } from '../ContextMenuItem';
+import { table } from 'console';
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -182,6 +183,8 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                     // targetDataDoc[this.props.fieldKey] = new List<Doc>([...docList, ...added]);
                     (targetDataDoc[this.props.fieldKey] as List<Doc>).push(...added);
                     targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now()));
+                    const lastModified = "lastModified";
+                    targetDataDoc[lastModified] = new DateField(new Date(Date.now()));
                 }
             }
         }
diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx
index 530004b54..972f4c066 100644
--- a/src/client/views/collections/SchemaTable.tsx
+++ b/src/client/views/collections/SchemaTable.tsx
@@ -218,19 +218,15 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                         background: col.color, padding: "2px",
                         display: "flex", cursor: "default", height: "100%",
                     }}>
-                    <FontAwesomeIcon icon={icon} size="lg" style={{ display: "inline", paddingBottom: "1px", paddingTop: "4px" }} />
+                    <FontAwesomeIcon onClick={e => this.props.openHeader(col, e.clientX, e.clientY)} icon={icon} size="lg" style={{ display: "inline", paddingBottom: "1px", paddingTop: "4px", cursor: "hand" }} />
                     {/* <div className="keys-dropdown"
                         style={{ display: "inline", zIndex: 1000 }}> */}
                     {keysDropdown}
                     {/* </div> */}
                     <div onClick={e => this.changeSorting(col)}
-                        style={{ width: 21, padding: 1, display: "inline", zIndex: 1, background: "inherit" }}>
+                        style={{ width: 21, padding: 1, display: "inline", zIndex: 1, background: "inherit", cursor: "hand" }}>
                         <FontAwesomeIcon icon={sortIcon} size="lg" />
                     </div>
-                    {/* <div onClick={e => this.props.openHeader(col, e.clientX, e.clientY)}
-                        style={{ float: "right", paddingRight: "6px", zIndex: 1, background: "inherit" }}>
-                        <FontAwesomeIcon icon={"compass"} size="sm" />
-                    </div> */}
                 </div>;
 
             return {
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 5a2c5400f..fb28ddae0 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -750,7 +750,6 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
 
     @observable filter = false;
 
-    //Make id layour document
     render() {
         this.props.Document._chromeStatus === "disabled";
         this.props.Document._searchDoc = true;
@@ -759,19 +758,20 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
         cols > 5 ? length = 1076 : length = cols * 205 + 51;
         let height = 0;
         const rows = this.children;
-        rows > 8 ? height = 31 + 31 * 8 : height = 31 * rows + 31;
+        rows > 6 ? height = 31 + 31 * 6 : height = 31 * rows + 31;
         return (
             <div style={{ pointerEvents: "all" }} className="searchBox-container">
                 <div className="searchBox-bar">
                     <div style={{ position: "absolute", left: 15 }}>{Doc.CurrentUserEmail}</div>
                     <div style={{ display: "flex", alignItems: "center" }}>
-                        <FontAwesomeIcon onPointerDown={SetupDrag(this.collectionRef, () => StrCast(this.layoutDoc._searchString) ? this.startDragCollection() : undefined)} icon={"search"} size="lg"
-                            style={{ color: "black", padding: 1, left: 35, position: "relative" }} />
-
+                        <Tooltip title={<div className="dash-tooltip" >drag search results as collection</div>} ><div>
+                            <FontAwesomeIcon onPointerDown={SetupDrag(this.collectionRef, () => StrCast(this.layoutDoc._searchString) ? this.startDragCollection() : undefined)} icon={"search"} size="lg"
+                                style={{ cursor: "hand", color: "black", padding: 1, left: 35, position: "relative" }} />
+                        </div></Tooltip>
                         <div style={{ cursor: "default", left: 250, position: "relative", }}>
                             <Tooltip title={<div className="dash-tooltip" >only display documents matching search</div>} ><div>
                                 <FontAwesomeIcon icon={"filter"} size="lg"
-                                    style={{ padding: 1, backgroundColor: this.filter ? "white" : "lightgray", color: this.filter ? "black" : "white" }}
+                                    style={{ cursor: "hand", padding: 1, backgroundColor: this.filter ? "white" : "lightgray", color: this.filter ? "black" : "white" }}
                                     onPointerDown={e => { e.stopPropagation(); SetupDrag(this.collectionRef, () => StrCast(this.layoutDoc._searchString) ? this.startDragCollection() : undefined); }}
                                     onClick={action(() => {
                                         ///DONT Change without emailing andy r first.
-- 
cgit v1.2.3-70-g09d2


From cf45a2398dce7af290bed364fa1bb8681134ce15 Mon Sep 17 00:00:00 2001
From: Andy Rickert <andrew_rickert@brown.edu>
Date: Mon, 10 Aug 2020 18:30:44 -0400
Subject: filter checkboxes

---
 src/client/views/MainView.tsx                      |   2 +-
 .../views/collections/CollectionSchemaCells.tsx    |  31 ++--
 .../views/collections/CollectionSchemaHeaders.tsx  | 200 ++++++++++++++++++++-
 .../views/collections/CollectionSchemaView.scss    |  41 +++++
 src/client/views/collections/CollectionView.tsx    | 111 ++++++------
 src/client/views/collections/SchemaTable.tsx       |  10 +-
 src/fields/Doc.ts                                  |   2 +
 src/server/ApiManagers/SearchManager.ts            |   2 +-
 src/server/websocket.ts                            |   3 +-
 9 files changed, 322 insertions(+), 80 deletions(-)

(limited to 'src/client/views/MainView.tsx')

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 744e5c68b..d7359d7e2 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -195,7 +195,7 @@ export class MainView extends React.Component {
             let check = false;
             const icon = "icon";
             targets.forEach((thing) => {
-                if (thing.className.toString() === "collectionSchemaView-searchContainer" || (thing as any)?.dataset[icon] === "filter" || thing.className.toString() === "collectionSchema-header-menuOptions") {
+                if (thing.className.toString() === "collectionSchemaView-searchContainer" || (thing as any)?.dataset[icon] === "filter" || thing.className.toString() === "collectionSchema-header-menuOptions" || thing.className.toString() === "altcollectionTimeView-treeView") {
                     check = true;
                 }
             });
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 64c925af2..2069255f7 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -34,6 +34,7 @@ import "react-datepicker/dist/react-datepicker.css";
 import { DateField } from "../../../fields/DateField";
 import { RichTextField } from "../../../fields/RichTextField";
 import { DocumentManager } from "../../util/DocumentManager";
+import { SearchUtil } from "../../util/SearchUtil";
 const path = require('path');
 
 library.add(faExpand);
@@ -218,19 +219,23 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
         const fieldIsDoc = (type === "document" && typeof field === "object") || (typeof field === "object" && doc);
 
         const onItemDown = async (e: React.PointerEvent) => {
-            //DocumentManager.Instance.FollowLink(undefined, this.props.rowProps.original, doc => this.props.addDocTab(doc, "onRight"), false);
-            let doc = Doc.GetProto(this.props.rowProps.original);
-            const targetContext = doc.links;
-            //const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined;
-            console.log(targetContext);
-            DocumentManager.Instance.jumpToDocument(this.props.rowProps.original, false, undefined, undefined);
-
-            //target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "onRight"), finished), targetNavContext, linkDoc, undefined, doc, finished);
-            //fieldIsDoc &&     
-            // SetupDrag(this._focusRef,
-            //     () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document,
-            //     this._document[props.fieldKey] instanceof Doc ? (doc: Doc | Doc[], target: Doc | undefined, addDoc: (newDoc: Doc | Doc[]) => any) => addDoc(doc) : this.props.moveDocument,
-            //     this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e);
+            if (this.props.Document._searchDoc !== undefined) {
+                let doc = Doc.GetProto(this.props.rowProps.original);
+                const aliasdoc = await SearchUtil.GetAliasesOfDocument(doc);
+                let targetContext = undefined;
+                if (aliasdoc.length > 0) {
+                    targetContext = Cast(aliasdoc[0].context, Doc) as Doc;
+                }
+                console.log(targetContext);
+                DocumentManager.Instance.jumpToDocument(this.props.rowProps.original, false, undefined, targetContext);
+            }
+            else {
+                fieldIsDoc &&
+                    SetupDrag(this._focusRef,
+                        () => this._document[props.fieldKey] instanceof Doc ? this._document[props.fieldKey] : this._document,
+                        this._document[props.fieldKey] instanceof Doc ? (doc: Doc | Doc[], target: Doc | undefined, addDoc: (newDoc: Doc | Doc[]) => any) => addDoc(doc) : this.props.moveDocument,
+                        this._document[props.fieldKey] instanceof Doc ? "alias" : this.props.Document.schemaDoc ? "copy" : undefined)(e);
+            }
         };
         const onPointerEnter = (e: React.PointerEvent): void => {
             if (e.buttons === 1 && SnappingManager.GetIsDragging() && (type === "document" || type === undefined)) {
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx
index bde7d054e..e8dd74dab 100644
--- a/src/client/views/collections/CollectionSchemaHeaders.tsx
+++ b/src/client/views/collections/CollectionSchemaHeaders.tsx
@@ -1,5 +1,5 @@
 import React = require("react");
-import { action, observable } from "mobx";
+import { action, observable, computed } from "mobx";
 import { observer } from "mobx-react";
 import "./CollectionSchemaView.scss";
 import { faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn, faSortAmountDown, faSortAmountUp, faTimes, faImage, faListUl, faCalendar } from '@fortawesome/free-solid-svg-icons';
@@ -9,9 +9,21 @@ import { ColumnType } from "./CollectionSchemaView";
 import { faFile } from "@fortawesome/free-regular-svg-icons";
 import { SchemaHeaderField, PastelSchemaPalette } from "../../../fields/SchemaHeaderField";
 import { undoBatch } from "../../util/UndoManager";
-import { Doc } from "../../../fields/Doc";
-import { StrCast } from "../../../fields/Types";
+import { Transform } from '../../util/Transform';
+import { Doc, DocListCast, Field, Opt } from "../../../fields/Doc";
+import { StrCast, Cast } from "../../../fields/Types";
 import { optionFocusAriaMessage } from "react-select/src/accessibility";
+import { TraceMobx } from "../../../fields/util";
+import { CollectionTreeView } from "./CollectionTreeView";
+import { returnEmptyFilter, returnFalse, emptyPath, returnZero, emptyFunction, returnOne } from "../../../Utils";
+import { RichTextField } from "../../../fields/RichTextField";
+import { Docs } from "../../documents/Documents";
+import { List } from "../../../fields/List";
+import { listSpec } from "../../../fields/Schema";
+import { ScriptField, ComputedField } from "../../../fields/ScriptField";
+import { DocumentType } from "../../documents/DocumentTypes";
+import { CollectionView } from "./CollectionView";
+
 const higflyout = require("@hig/flyout");
 export const { anchorPoints } = higflyout;
 export const Flyout = higflyout.default;
@@ -287,7 +299,12 @@ export interface KeysDropdownProps {
     setIsEditing: (isEditing: boolean) => void;
     width?: string;
     docs?: Doc[];
-
+    Document?: Doc;
+    dataDoc?: Doc;
+    fieldKey?: string;
+    ContainingCollectionDoc?: Doc;
+    ContainingCollectionView?: CollectionView;
+    active?: (outsideReaction?: boolean) => boolean;
 }
 @observer
 export class KeysDropdown extends React.Component<KeysDropdownProps> {
@@ -426,7 +443,8 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
         let keyOptions: string[] = [];
         const colpos = this._searchTerm.indexOf(":");
         const temp = this._searchTerm.slice(colpos + 1, this._searchTerm.length);
-        this.props.docs?.forEach((doc) => {
+        let docs = DocListCast(this.props.dataDoc![this.props.fieldKey!]);
+        docs.forEach((doc) => {
             const key = StrCast(doc[this._key]);
             if (keyOptions.includes(key) === false && key.includes(temp)) {
                 keyOptions.push(key);
@@ -438,7 +456,11 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
             return <div key={key} className="key-option" style={{
                 border: "1px solid lightgray", width: this.props.width, maxWidth: this.props.width, overflowX: "hidden", background: "white", backgroundColor: "white",
             }}
-                onPointerDown={e => e.stopPropagation()} onClick={() => { this.onSelectValue(key); }}>{key}</div>;
+            >
+                <input type="checkbox" onChange={(e) => { e.target.checked === true ? Doc.setDocFilter(this.props.Document!, this._key, key, "check") : Doc.setDocFilter(this.props.Document!, this._key, key, undefined) }} ></input>
+                {key}
+
+            </div>;
         });
         if (options.length === 0) {
             this.defaultMenuHeight = 0;
@@ -457,8 +479,172 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
         return options;
     }
 
+
+    // @action
+    // renderFilterOptions = (): JSX.Element[] | JSX.Element => {
+    //     this.facetClick(this._key);
+    //     return <div>
+    //         {this.filterView}
+    //     </div>
+    // }
     @observable defaultMenuHeight = 0;
 
+
+    facetClick = (facetHeader: string) => {
+        facetHeader = this._key;
+        let newFacet: Opt<Doc>;
+        if (this.props.Document !== undefined) {
+            const facetCollection = this.props.Document;
+            // const found = DocListCast(facetCollection[this.props.fieldKey + "-filter"]).findIndex(doc => doc.title === facetHeader);
+            // if (found !== -1) {
+            //     console.log("found not n-1");
+            //     (facetCollection[this.props.fieldKey + "-filter"] as List<Doc>).splice(found, 1);
+            //     const docFilter = Cast(this.props.Document._docFilters, listSpec("string"));
+            //     if (docFilter) {
+            //         let index: number;
+            //         while ((index = docFilter.findIndex(item => item === facetHeader)) !== -1) {
+            //             docFilter.splice(index, 3);
+            //         }
+            //     }
+            //     const docRangeFilters = Cast(this.props.Document._docRangeFilters, listSpec("string"));
+            //     if (docRangeFilters) {
+            //         let index: number;
+            //         while ((index = docRangeFilters.findIndex(item => item === facetHeader)) !== -1) {
+            //             docRangeFilters.splice(index, 3);
+            //         }
+            //     }
+            // }
+
+
+
+            console.log("found is n-1");
+            const allCollectionDocs = DocListCast(this.props.dataDoc![this.props.fieldKey!]);
+            var rtfields = 0;
+            const facetValues = Array.from(allCollectionDocs.reduce((set, child) => {
+                const field = child[facetHeader] as Field;
+                const fieldStr = Field.toString(field);
+                if (field instanceof RichTextField || (typeof (field) === "string" && fieldStr.split(" ").length > 2)) rtfields++;
+                return set.add(fieldStr);
+            }, new Set<string>()));
+
+            let nonNumbers = 0;
+            let minVal = Number.MAX_VALUE, maxVal = -Number.MAX_VALUE;
+            facetValues.map(val => {
+                const num = Number(val);
+                if (Number.isNaN(num)) {
+                    nonNumbers++;
+                } else {
+                    minVal = Math.min(num, minVal);
+                    maxVal = Math.max(num, maxVal);
+                }
+            });
+            if (facetHeader === "text" || rtfields / allCollectionDocs.length > 0.1) {
+                console.log("Case1");
+                newFacet = Docs.Create.TextDocument("", { _width: 100, _height: 25, 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.target = this.props.Document;
+                newFacet._textBoxPadding = 4;
+                const scriptText = `setDocFilter(this.target, "${facetHeader}", text, "match")`;
+                newFacet.onTextChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, text: "string" });
+            } else if (nonNumbers / facetValues.length < .1) {
+                console.log("Case2");
+                newFacet = Docs.Create.SliderDocument({ title: facetHeader, treeViewExpandedView: "layout", treeViewOpen: true });
+                const newFacetField = Doc.LayoutFieldKey(newFacet);
+                const ranged = Doc.readDocRangeFilter(this.props.Document, facetHeader);
+                Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox
+                const extendedMinVal = minVal - Math.min(1, Math.abs(maxVal - minVal) * .05);
+                const extendedMaxVal = maxVal + Math.min(1, Math.abs(maxVal - minVal) * .05);
+                newFacet[newFacetField + "-min"] = ranged === undefined ? extendedMinVal : ranged[0];
+                newFacet[newFacetField + "-max"] = ranged === undefined ? extendedMaxVal : ranged[1];
+                Doc.GetProto(newFacet)[newFacetField + "-minThumb"] = extendedMinVal;
+                Doc.GetProto(newFacet)[newFacetField + "-maxThumb"] = extendedMaxVal;
+                newFacet.target = this.props.Document;
+                const scriptText = `setDocFilterRange(this.target, "${facetHeader}", range)`;
+                newFacet.onThumbChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, range: "number" });
+                Doc.AddDocToList(facetCollection, this.props.fieldKey + "-filter", newFacet);
+            } else {
+                console.log("Case3");
+                newFacet = new Doc();
+                newFacet.title = facetHeader;
+                newFacet.treeViewOpen = true;
+                newFacet.type = DocumentType.COL;
+                const capturedVariables = { layoutDoc: this.props.Document, dataDoc: this.props.dataDoc! };
+                this.props.Document.data = ComputedField.MakeFunction(`readFacetData(layoutDoc, dataDoc, "${this.props.fieldKey}", "${facetHeader}")`, {}, capturedVariables);
+                // this.props.Document.data
+            }
+            //newFacet && Doc.AddDocToList(facetCollection, this.props.fieldKey + "-filter", newFacet);
+        }
+    }
+
+
+    get ignoreFields() { return ["_docFilters", "_docRangeFilters"]; }
+
+    @computed get scriptField() {
+        console.log("we kinda made it");
+        const scriptText = "setDocFilter(containingTreeView, heading, this.title, checked)";
+        const script = ScriptField.MakeScript(scriptText, { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name });
+        return script ? () => script : undefined;
+    }
+    filterBackground = () => "rgba(105, 105, 105, 0.432)";
+
+
+    // @computed get filterView() {
+    //     TraceMobx();
+    //     if (this.props.Document !== undefined) {
+    //         //const facetCollection = this.props.Document;
+    //         // const flyout = (
+    //         //     <div className="collectionTimeView-flyout" style={{ width: `${this.facetWidth()}`, height: this.props.PanelHeight() - 30 }} onWheel={e => e.stopPropagation()}>
+    //         //         {this._allFacets.map(facet => <label className="collectionTimeView-flyout-item" key={`${facet}`} onClick={e => this.facetClick(facet)}>
+    //         //             <input type="checkbox" onChange={e => { }} checked={DocListCast(this.props.Document[this.props.fieldKey + "-filter"]).some(d => d.title === facet)} />
+    //         //             <span className="checkmark" />
+    //         //             {facet}
+    //         //         </label>)}
+    //         //     </div>
+    //         // );
+    //         return <div className="altcollectionTimeView-treeView">
+    //             <div className="altcollectionTimeView-tree" key="tree">
+    //                 <CollectionTreeView
+    //                     PanelPosition={""}
+    //                     Document={this.props.Document}
+    //                     DataDoc={this.props.Document}
+    //                     fieldKey={this.props.fieldKey!}
+    //                     CollectionView={undefined}
+    //                     docFilters={returnEmptyFilter}
+    //                     ContainingCollectionDoc={this.props.ContainingCollectionDoc!}
+    //                     ContainingCollectionView={this.props.ContainingCollectionView!}
+    //                     PanelWidth={() => 200}
+    //                     PanelHeight={() => 200}
+    //                     NativeHeight={returnZero}
+    //                     NativeWidth={returnZero}
+    //                     LibraryPath={emptyPath}
+    //                     rootSelected={returnFalse}
+    //                     renderDepth={1}
+    //                     dropAction={undefined}
+    //                     ScreenToLocalTransform={Transform.Identity}
+    //                     addDocTab={returnFalse}
+    //                     pinToPres={returnFalse}
+    //                     isSelected={returnFalse}
+    //                     select={returnFalse}
+    //                     bringToFront={emptyFunction}
+    //                     active={this.props.active!}
+    //                     whenActiveChanged={returnFalse}
+    //                     treeViewHideTitle={true}
+    //                     ContentScaling={returnOne}
+    //                     focus={returnFalse}
+    //                     treeViewHideHeaderFields={true}
+    //                     onCheckedClick={this.scriptField}
+    //                     ignoreFields={this.ignoreFields}
+    //                     annotationsKey={""}
+    //                     dontRegisterView={true}
+    //                     backgroundColor={this.filterBackground}
+    //                     moveDocument={returnFalse}
+    //                     removeDocument={returnFalse}
+    //                     addDocument={returnFalse} />
+    //             </div>
+    //         </div>;
+    //     }
+    // }
+
     render() {
         return (
             <div className="keys-dropdown" style={{ zIndex: 10, width: this.props.width, maxWidth: this.props.width }}>
@@ -470,7 +656,7 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> {
                         e.stopPropagation();
                     }} onFocus={this.onFocus} onBlur={this.onBlur}></input>
                 <div className="keys-options-wrapper" style={{
-                    width: this.props.width, maxWidth: this.props.width, overflow: "scroll", height: this.defaultMenuHeight,
+                    width: this.props.width, maxWidth: this.props.width, overflow: "scroll", height: "auto",
                 }}
                     onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerOut}>
                     {this._searchTerm.includes(":") ?
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 86bf9d0e0..ee643b86b 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -357,6 +357,47 @@ button.add-column {
     }
 }
 
+.altcollectionTimeView-treeView {
+    display: flex;
+    flex-direction: column;
+    width: 175px;
+    height: auto;
+    position: fixed;
+    border-left: solid 1px;
+    z-index: 1;
+
+    .collectionTimeView-addfacet {
+        display: inline-block;
+        width: 200px;
+        height: 30px;
+        background: darkGray;
+        text-align: left;
+
+        .collectionTimeView-button {
+            align-items: center;
+            display: flex;
+            width: 100%;
+            height: 100%;
+
+            .collectionTimeView-span {
+                margin: auto;
+            }
+        }
+
+        >div,
+        >div>div {
+            width: 100%;
+            height: 100%;
+        }
+    }
+
+    .altcollectionTimeView-tree {
+        display: inline-block;
+        width: 100%;
+        height: calc(100% - 30px);
+    }
+}
+
 .collectionSchema-row {
     height: 100%;
     background-color: white;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 30747ff4f..73a5566d6 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -513,56 +513,56 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                 </label>)}
             </div>
         );
-        return !this._facetWidth || this.props.dontRegisterView ? (null) :
-            <div className="collectionTimeView-treeView" style={{ width: `${this.facetWidth()}px`, overflow: this.facetWidth() < 15 ? "hidden" : undefined }}>
-                <div className="collectionTimeView-addFacet" style={{ width: `${this.facetWidth()}px` }} onPointerDown={e => e.stopPropagation()}>
-                    <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={flyout}>
-                        <div className="collectionTimeView-button">
-                            <FontAwesomeIcon icon={faEdit} size={"lg"} />
-                            <span className="collectionTimeView-span">Facet Filters</span>
-                        </div>
-                    </Flyout>
-                </div>
-                <div className="collectionTimeView-tree" key="tree">
-                    <CollectionTreeView
-                        PanelPosition={""}
-                        Document={facetCollection}
-                        DataDoc={facetCollection}
-                        fieldKey={`${this.props.fieldKey}-filter`}
-                        CollectionView={this}
-                        docFilters={returnEmptyFilter}
-                        ContainingCollectionDoc={this.props.ContainingCollectionDoc}
-                        ContainingCollectionView={this.props.ContainingCollectionView}
-                        PanelWidth={this.facetWidth}
-                        PanelHeight={this.props.PanelHeight}
-                        NativeHeight={returnZero}
-                        NativeWidth={returnZero}
-                        LibraryPath={emptyPath}
-                        rootSelected={this.props.rootSelected}
-                        renderDepth={1}
-                        dropAction={this.props.dropAction}
-                        ScreenToLocalTransform={this.props.ScreenToLocalTransform}
-                        addDocTab={returnFalse}
-                        pinToPres={returnFalse}
-                        isSelected={returnFalse}
-                        select={returnFalse}
-                        bringToFront={emptyFunction}
-                        active={this.props.active}
-                        whenActiveChanged={returnFalse}
-                        treeViewHideTitle={true}
-                        ContentScaling={returnOne}
-                        focus={returnFalse}
-                        treeViewHideHeaderFields={true}
-                        onCheckedClick={this.scriptField}
-                        ignoreFields={this.ignoreFields}
-                        annotationsKey={""}
-                        dontRegisterView={true}
-                        backgroundColor={this.filterBackground}
-                        moveDocument={returnFalse}
-                        removeDocument={returnFalse}
-                        addDocument={returnFalse} />
-                </div>
-            </div>;
+
+        return !this._facetWidth || this.props.dontRegisterView ? (null) : <div className="collectionTimeView-treeView" style={{ width: `${this.facetWidth()}px`, overflow: this.facetWidth() < 15 ? "hidden" : undefined }}>
+            <div className="collectionTimeView-addFacet" style={{ width: `${this.facetWidth()}px` }} onPointerDown={e => e.stopPropagation()}>
+                <Flyout anchorPoint={anchorPoints.LEFT_TOP} content={flyout}>
+                    <div className="collectionTimeView-button">
+                        <FontAwesomeIcon icon={faEdit} size={"lg"} />
+                        <span className="collectionTimeView-span">Facet Filters</span>
+                    </div>
+                </Flyout>
+            </div>
+            <div className="collectionTimeView-tree" key="tree">
+                <CollectionTreeView
+                    PanelPosition={""}
+                    Document={facetCollection}
+                    DataDoc={facetCollection}
+                    fieldKey={`${this.props.fieldKey}-filter`}
+                    CollectionView={this}
+                    docFilters={returnEmptyFilter}
+                    ContainingCollectionDoc={this.props.ContainingCollectionDoc}
+                    ContainingCollectionView={this.props.ContainingCollectionView}
+                    PanelWidth={this.facetWidth}
+                    PanelHeight={this.props.PanelHeight}
+                    NativeHeight={returnZero}
+                    NativeWidth={returnZero}
+                    LibraryPath={emptyPath}
+                    rootSelected={this.props.rootSelected}
+                    renderDepth={1}
+                    dropAction={this.props.dropAction}
+                    ScreenToLocalTransform={this.props.ScreenToLocalTransform}
+                    addDocTab={returnFalse}
+                    pinToPres={returnFalse}
+                    isSelected={returnFalse}
+                    select={returnFalse}
+                    bringToFront={emptyFunction}
+                    active={this.props.active}
+                    whenActiveChanged={returnFalse}
+                    treeViewHideTitle={true}
+                    ContentScaling={returnOne}
+                    focus={returnFalse}
+                    treeViewHideHeaderFields={true}
+                    onCheckedClick={this.scriptField}
+                    ignoreFields={this.ignoreFields}
+                    annotationsKey={""}
+                    dontRegisterView={true}
+                    backgroundColor={this.filterBackground}
+                    moveDocument={returnFalse}
+                    removeDocument={returnFalse}
+                    addDocument={returnFalse} />
+            </div>
+        </div>;
     }
 
     childLayoutTemplate = () => this.props.childLayoutTemplate?.() || Cast(this.props.Document.childLayoutTemplate, Doc, null);
@@ -595,11 +595,12 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
                         Utils.CorsProxy(Cast(d.data, ImageField)!.url.href) : Cast(d.data, ImageField)!.url.href
                     :
                     ""))}
-            {(Doc.UserDoc()?.noviceMode || !this.props.isSelected() && !this.props.Document.forceActive) || this.props.Document.hideFilterView ? (null) :
-                <div className="collectionView-filterDragger" title="library View Dragger" onPointerDown={this.onPointerDown}
-                    style={{ right: this.facetWidth() - 1, top: this.props.Document._viewType === CollectionViewType.Docking ? "25%" : "55%" }} />
-            }
-            {Doc.UserDoc()?.noviceMode || this.facetWidth() < 10 ? (null) : this.filterView}
+            {/* {(Doc.UserDoc()?.noviceMode || !this.props.isSelected() && !this.props.Document.forceActive) || this.props.Document.hideFilterView ? (null) : */}
+            <div className="collectionView-filterDragger" title="library View Dragger" onPointerDown={this.onPointerDown}
+                style={{ right: this.facetWidth() - 1, top: this.props.Document._viewType === CollectionViewType.Docking ? "25%" : "55%" }} />
+            {/* } */}
+            {/* {Doc.UserDoc()?.noviceMode || this.facetWidth() < 10 ? (null) : this.filterView} */}
+            {this.filterView};
         </div>);
     }
 }
diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx
index 972f4c066..d8756aae3 100644
--- a/src/client/views/collections/SchemaTable.tsx
+++ b/src/client/views/collections/SchemaTable.tsx
@@ -177,9 +177,9 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                 }
             );
         }
+        this.props.active
 
         const cols = this.props.columns.map(col => {
-
             const keysDropdown = <KeysDropdown
                 keyValue={col.heading}
                 possibleKeys={possibleKeys}
@@ -189,6 +189,14 @@ export class SchemaTable extends React.Component<SchemaTableProps> {
                 onSelect={this.props.changeColumns}
                 setIsEditing={this.props.setHeaderIsEditing}
                 docs={this.props.childDocs}
+                Document={this.props.Document}
+                dataDoc={this.props.dataDoc}
+                fieldKey={this.props.fieldKey}
+                ContainingCollectionDoc={this.props.ContainingCollectionDoc}
+                ContainingCollectionView={this.props.ContainingCollectionView}
+                active={this.props.active}
+
+
                 // try commenting this out
                 width={"100%"}
             />;
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 6bfe91378..7769fd337 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1036,6 +1036,8 @@ export namespace Doc {
     // all documents with the specified value for the specified key are included/excluded 
     // based on the modifiers :"check", "x", undefined
     export function setDocFilter(container: Doc, key: string, value: any, modifiers?: "match" | "check" | "x" | undefined) {
+        console.log("WE REALLY MADE IT");
+        console.log(container, key, value, modifiers);
         const docFilters = Cast(container._docFilters, listSpec("string"), []);
         runInAction(() => {
             for (let i = 0; i < docFilters.length; i += 3) {
diff --git a/src/server/ApiManagers/SearchManager.ts b/src/server/ApiManagers/SearchManager.ts
index 7251e07a1..753c31fcf 100644
--- a/src/server/ApiManagers/SearchManager.ts
+++ b/src/server/ApiManagers/SearchManager.ts
@@ -176,7 +176,7 @@ export namespace SolrManager {
         "audio": ["_t", "url"],
         "web": ["_t", "url"],
         "date": ["_d", value => new Date(value.date).toISOString()],
-        // "proxy": ["_i", "fieldId"],
+        "proxy": ["_i", "fieldId"],
         "list": ["_l", list => {
             const results = [];
             for (const value of list.fields) {
diff --git a/src/server/websocket.ts b/src/server/websocket.ts
index 63cfa41f0..798c79164 100644
--- a/src/server/websocket.ts
+++ b/src/server/websocket.ts
@@ -230,8 +230,7 @@ export namespace WebSocket {
         "script": ["_t", value => value.script.originalScript],
         "RichTextField": ["_t", value => value.Text],
         "date": ["_d", value => new Date(value.date).toISOString()],
-        // "proxy": ["_i", "fieldId"],
-        // "proxy": ["", "fieldId"],
+        "proxy": ["_i", "fieldId"],
         "list": ["_l", list => {
             const results = [];
             for (const value of list.fields) {
-- 
cgit v1.2.3-70-g09d2


From 201dc881e15292ee4a013c72b9e473779cf14e18 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 11 Aug 2020 10:22:54 -0400
Subject: updated how background colors work

---
 src/client/documents/Documents.ts                  |  1 +
 src/client/util/CurrentUserUtils.ts                | 13 ++++--
 src/client/util/SettingsManager.tsx                |  2 +-
 src/client/views/MainView.tsx                      |  6 +--
 .../views/collections/CollectionCarouselView.tsx   |  2 +-
 .../views/collections/CollectionDockingView.tsx    |  4 +-
 .../views/collections/CollectionTreeView.tsx       |  2 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 .../collections/collectionFreeForm/MarqueeView.tsx | 46 ++++++++++------------
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  4 +-
 src/client/views/nodes/DocHolderBox.tsx            |  2 +-
 src/client/views/nodes/DocumentView.tsx            |  4 +-
 src/client/views/nodes/FieldView.tsx               |  2 +-
 src/client/views/nodes/FontIconBox.tsx             |  2 +-
 src/client/views/nodes/LinkBox.tsx                 |  2 +-
 src/client/views/nodes/MenuIconBox.tsx             |  6 +--
 16 files changed, 51 insertions(+), 49 deletions(-)

(limited to 'src/client/views/MainView.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 070fdf407..956a5645c 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -174,6 +174,7 @@ export interface DocumentOptions {
     onPointerUp?: ScriptField;
     dropConverter?: ScriptField; // script to run when documents are dropped on this Document.
     dragFactory?: Doc; // document to create when dragging with a suitable onDragStart script
+    clickFactory?: Doc; // document to create when clicking on a button with a suitable onClick script
     onDragStart?: ScriptField; //script to execute at start of drag operation --  e.g., when a "creator" button is dragged this script generates a different document to drop
     clipboard?: Doc;
     UseCors?: boolean;
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index e8c4da425..10fdbf534 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -387,7 +387,7 @@ export class CurrentUserUtils {
 
     static creatorBtnDescriptors(doc: Doc): {
         title: string, toolTip: string, icon: string, drag?: string, ignoreClick?: boolean,
-        click?: string, ischecked?: string, activeInkPen?: Doc, backgroundColor?: string, dragFactory?: Doc, noviceMode?: boolean
+        click?: string, ischecked?: string, activeInkPen?: Doc, backgroundColor?: string, dragFactory?: Doc, noviceMode?: boolean, clickFactory?: Doc
     }[] {
         if (doc.emptyPresentation === undefined) {
             doc.emptyPresentation = Docs.Create.PresDocument(new List<Doc>(),
@@ -397,6 +397,9 @@ export class CurrentUserUtils {
             doc.emptyCollection = Docs.Create.FreeformDocument([],
                 { _nativeWidth: undefined, _nativeHeight: undefined, _width: 150, _height: 100, title: "freeform", system: true });
         }
+        if (doc.emptyPane === undefined) {
+            doc.emptyPane = Docs.Create.FreeformDocument([], { _nativeWidth: undefined, _nativeHeight: undefined, title: "Untitled Collection", system: true });
+        }
         if (doc.emptyComparison === undefined) {
             doc.emptyComparison = Docs.Create.ComparisonDocument({ title: "compare", _width: 300, _height: 300, system: true });
         }
@@ -427,7 +430,7 @@ export class CurrentUserUtils {
             this.setupActiveMobileMenu(doc);
         }
         return [
-            { toolTip: "Drag a collection", title: "Col", icon: "folder", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyCollection as Doc, noviceMode: true },
+            { toolTip: "Drag a collection", title: "Col", icon: "folder", click: 'openOnRight(getCopy(this.clickFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyCollection as Doc, noviceMode: true, clickFactory: doc.emptyPane as Doc, },
             { toolTip: "Drag a web page", title: "Web", icon: "globe-asia", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyWebpage as Doc, noviceMode: true },
             { toolTip: "Drag a cat image", title: "Image", icon: "cat", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyImage as Doc },
             { toolTip: "Drag a comparison box", title: "Compare", icon: "columns", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyComparison as Doc, noviceMode: true },
@@ -466,7 +469,7 @@ export class CurrentUserUtils {
             }
         }
         const buttons = CurrentUserUtils.creatorBtnDescriptors(doc).filter(d => !alreadyCreatedButtons?.includes(d.title));
-        const creatorBtns = buttons.map(({ title, toolTip, icon, ignoreClick, drag, click, ischecked, activeInkPen, backgroundColor, dragFactory, noviceMode }) => Docs.Create.FontIconDocument({
+        const creatorBtns = buttons.map(({ title, toolTip, icon, ignoreClick, drag, click, ischecked, activeInkPen, backgroundColor, dragFactory, noviceMode, clickFactory }) => Docs.Create.FontIconDocument({
             _nativeWidth: 50, _nativeHeight: 50, _width: 50, _height: 50,
             icon,
             title,
@@ -480,6 +483,7 @@ export class CurrentUserUtils {
             backgroundColor,
             removeDropProperties: new List<string>(["dropAction"]),
             dragFactory,
+            clickFactory,
             userDoc: noviceMode ? undefined as any : doc,
             hidden: noviceMode ? undefined as any : ComputedField.MakeFunction("self.userDoc.noviceMode"), system: true
         }));
@@ -908,7 +912,8 @@ export class CurrentUserUtils {
         doc.fontFamily = StrCast(doc.fontFamily, "Arial");
         doc.fontColor = StrCast(doc.fontColor, "black");
         doc.fontHighlight = StrCast(doc.fontHighlight, "");
-        doc.defaultColor = StrCast(doc.defaultColor, "white");
+        doc["default-collection-background"] = StrCast(doc["default-collection-background"], "white");
+        doc["default-collection-nested-background"] = Cast(doc["default-collection-nested-background"], "string", null);
         doc.noviceMode = BoolCast(doc.noviceMode, true);
         doc["constants-snapThreshold"] = NumCast(doc["constants-snapThreshold"], 10); //
         doc["constants-dragThreshold"] = NumCast(doc["constants-dragThreshold"], 4); //
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index e3b91925a..737682cf7 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -56,7 +56,7 @@ export default class SettingsManager extends React.Component<{}> {
     @undoBatch selectUserMode = action((e: React.ChangeEvent) => Doc.UserDoc().noviceMode = (e.currentTarget as any)?.value === "Novice");
     @undoBatch changeFontFamily = action((e: React.ChangeEvent) => Doc.UserDoc().fontFamily = (e.currentTarget as any).value);
     @undoBatch changeFontSize = action((e: React.ChangeEvent) => Doc.UserDoc().fontSize = (e.currentTarget as any).value);
-    @undoBatch switchColor = action((color: ColorState) => Doc.UserDoc().defaultColor = String(color.hex));
+    @undoBatch switchColor = action((color: ColorState) => Doc.UserDoc()["default-collection-background"] = String(color.hex));
     @undoBatch
     playgroundModeToggle = action(() => {
         this.playgroundMode = !this.playgroundMode;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 4d5dfc99e..3cbc00c92 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -258,7 +258,7 @@ export class MainView extends React.Component {
             y: 400,
             _width: this._panelWidth * .7 - this.propertiesWidth() * 0.7,
             _height: this._panelHeight,
-            title: "Collection " + workspaceCount,
+            title: "Untitled Collection",
         };
         const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
         const workspaceDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myCatalog as Doc] }], { title: `Workspace ${workspaceCount}` }, id, "row");
@@ -332,7 +332,7 @@ export class MainView extends React.Component {
     getPHeight = () => this._panelHeight;
     getContentsHeight = () => this._panelHeight - this._buttonBarHeight;
 
-    defaultBackgroundColors = (doc: Opt<Doc>) => {
+    defaultBackgroundColors = (doc: Opt<Doc>, renderDepth: number) => {
         if (this.panelContent === doc?.title) return "lightgrey";
 
         if (doc?.type === DocumentType.COL) {
@@ -342,7 +342,7 @@ export class MainView extends React.Component {
                 || doc.title === "Advanced Item Prototypes" || doc.title === "all Creators") {
                 return "lightgrey";
             }
-            return StrCast(Doc.UserDoc().defaultColor);
+            return renderDepth > 0 ? StrCast(Doc.UserDoc()["default-collection-nested-background"]) : StrCast(Doc.UserDoc()["default-collection-background"]);
         }
         if (this.darkScheme) {
             switch (doc?.type) {
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 27aea4b99..8a27f8102 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -64,7 +64,7 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
                 </div>
                 <div className="collectionCarouselView-caption" key="caption"
                     style={{
-                        background: StrCast(this.layoutDoc._captionBackgroundColor, this.props.backgroundColor?.(this.props.Document)),
+                        background: StrCast(this.layoutDoc._captionBackgroundColor, this.props.backgroundColor?.(this.props.Document, this.props.renderDepth)),
                         color: StrCast(this.layoutDoc._captionColor, StrCast(this.layoutDoc.color)),
                         borderRadius: StrCast(this.layoutDoc._captionBorderRounding),
                     }}>
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 3691e844f..7db846f72 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -758,7 +758,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
         this.props.glContainer.layoutManager.on("activeContentItemChanged", this.onActiveContentItemChanged);
         this.props.glContainer.on("tab", this.onActiveContentItemChanged);
         this.onActiveContentItemChanged();
-        this._tabReaction = reaction(() => ({ views: SelectionManager.SelectedDocuments(), color: StrCast(this._document?._backgroundColor, "white") }),
+        this._tabReaction = reaction(() => ({ views: SelectionManager.SelectedDocuments(), color: StrCast(this._document?._backgroundColor, this._document && CollectionDockingView.Instance.props.backgroundColor?.(this._document, 0) || "white") }),
             (data) => {
                 const selected = data.views.some(v => Doc.AreProtosEqual(v.props.Document, this._document));
                 this._tab && (this._tab.style.backgroundColor = selected ? data.color : "");
@@ -896,7 +896,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
     renderMiniMap() {
         return <div className="miniMap" style={{
             width: this.returnMiniSize(), height: this.returnMiniSize(), background: StrCast(this._document!._backgroundColor,
-                StrCast(this._document!.backgroundColor, CollectionDockingView.Instance.props.backgroundColor?.(this._document!))),
+                StrCast(this._document!.backgroundColor, CollectionDockingView.Instance.props.backgroundColor?.(this._document!, 0))),
         }}>
             <CollectionFreeFormView
                 Document={this._document!}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 3c7471d7c..dc88917cc 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -813,7 +813,7 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
             <div className="collectionTreeView-container" onContextMenu={this.onContextMenu}>
                 <div className="collectionTreeView-dropTarget" id="body"
                     style={{
-                        background: this.props.backgroundColor?.(this.doc),
+                        background: this.props.backgroundColor?.(this.doc, this.props.renderDepth),
                         paddingLeft: `${NumCast(this.doc._xPadding, 10)}px`,
                         paddingRight: `${NumCast(this.doc._xPadding, 10)}px`,
                         paddingTop: `${NumCast(this.doc._yPadding, 20)}px`,
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 2b8e949b1..17ae7037e 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -378,7 +378,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     }
 
     getClusterColor = (doc: Doc) => {
-        let clusterColor = this.props.backgroundColor?.(doc);
+        let clusterColor = this.props.backgroundColor?.(doc, this.props.renderDepth + 1);
         const cluster = NumCast(doc.cluster);
         if (this.Document.useClusters) {
             if (this._clusterSets.length <= cluster) {
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 1a708d67d..68b8ed041 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -21,6 +21,7 @@ import { CollectionView } from "../CollectionView";
 import MarqueeOptionsMenu from "./MarqueeOptionsMenu";
 import "./MarqueeView.scss";
 import React = require("react");
+import { ContextMenuItem } from "../../ContextMenuItem";
 
 interface MarqueeViewProps {
     getContainerTransform: () => Transform;
@@ -70,23 +71,19 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
     onKeyPress = (e: KeyboardEvent) => {
         //make textbox and add it to this collection
         // tslint:disable-next-line:prefer-const
-        let [x, y] = this.props.getTransform().transformPoint(this._downX, this._downY);
+        const cm = ContextMenu.Instance;
+        const [x, y] = this.props.getTransform().transformPoint(this._downX, this._downY);
         if (e.key === "?") {
-            ContextMenu.Instance.setDefaultItem("?", (str: string) => {
-                const textDoc = Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, {
-                    _width: 200, x, y, _nativeHeight: 962, _nativeWidth: 850, isAnnotating: false,
-                    title: "bing", UseCors: true
-                });
-                this.props.addDocTab(textDoc, "onRight");
-            });
+            cm.setDefaultItem("?", (str: string) => this.props.addDocTab(
+                Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, { _width: 200, x, y, _nativeHeight: 962, _nativeWidth: 850, isAnnotating: false, title: "bing", UseCors: true }), "onRight"));
 
-            ContextMenu.Instance.displayMenu(this._downX, this._downY);
+            cm.displayMenu(this._downX, this._downY);
             e.stopPropagation();
         } else
             if (e.key === ":") {
                 DocUtils.addDocumentCreatorMenuItems(this.props.addLiveTextDocument, this.props.addDocument, x, y);
 
-                ContextMenu.Instance.displayMenu(this._downX, this._downY);
+                cm.displayMenu(this._downX, this._downY);
                 e.stopPropagation();
             } else if (e.key === "a" && (e.ctrlKey || e.metaKey)) {
                 e.preventDefault();
@@ -359,24 +356,23 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
         this.hideMarquee();
     }
 
-    getCollection = (selected: Doc[], creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, isBackground?: boolean) => {
-        const bounds = this.Bounds;
-        // const inkData = this.ink ? this.ink.inkData : undefined;
-        const newCollection = (creator || Docs.Create.FreeformDocument)(selected, {
-            x: bounds.left,
-            y: bounds.top,
-            _panX: 0,
-            _panY: 0,
-            isBackground,
-            backgroundColor: this.props.isAnnotationOverlay ? "#00000015" : isBackground ? "cyan" : undefined,
-            _width: bounds.width,
-            _height: bounds.height,
-            title: "a nested collection",
-        });
+    getCollection = action((selected: Doc[], creator: Opt<(documents: Array<Doc>, options: DocumentOptions, id?: string) => Doc>, isBackground?: boolean) => {
+        const newCollection = creator ? creator(selected, { title: "nested stack", }) : ((doc: Doc) => {
+            Doc.GetProto(doc).data = new List<Doc>(selected);
+            Doc.GetProto(doc).title = "nested freeform";
+            doc._panX = doc._panY = 0;
+            return doc;
+        })(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true));
+        newCollection.isBackground = isBackground;
+        newCollection.backgroundColor = this.props.isAnnotationOverlay ? "#00000015" : isBackground ? "cyan" : undefined;
+        newCollection._width = this.Bounds.width;
+        newCollection._height = this.Bounds.height;
+        newCollection.x = this.Bounds.left;
+        newCollection.y = this.Bounds.top;
         selected.forEach(d => d.context = newCollection);
         this.hideMarquee();
         return newCollection;
-    }
+    });
 
     @action
     pileup = (e: KeyboardEvent | React.PointerEvent | undefined) => {
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 42a42ddf1..63869bd50 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -267,13 +267,13 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     NativeHeight = () => this.nativeHeight;
     render() {
         TraceMobx();
-        const backgroundColor = StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document);
+        const backgroundColor = StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document, this.props.renderDepth);
         return <div className="collectionFreeFormDocumentView-container"
             style={{
                 boxShadow:
                     this.Opacity === 0 ? undefined :  // if it's not visible, then no shadow
                         this.layoutDoc.z ? `#9c9396  ${StrCast(this.layoutDoc.boxShadow, "10px 10px 0.9vw")}` :  // if it's a floating doc, give it a big shadow
-                            this.props.backgroundHalo?.() && this.props.Document.type !== DocumentType.INK ? (`${this.props.backgroundColor?.(this.props.Document)} ${StrCast(this.layoutDoc.boxShadow, `0vw 0vw ${(this.layoutDoc.isBackground ? 100 : 50) / this.props.ContentScaling()}px`)}`) :  // if it's just in a cluster, make the shadown roughly match the cluster border extent
+                            this.props.backgroundHalo?.() && this.props.Document.type !== DocumentType.INK ? (`${this.props.backgroundColor?.(this.props.Document, this.props.renderDepth)} ${StrCast(this.layoutDoc.boxShadow, `0vw 0vw ${(this.layoutDoc.isBackground ? 100 : 50) / this.props.ContentScaling()}px`)}`) :  // if it's just in a cluster, make the shadown roughly match the cluster border extent
                                 this.layoutDoc.isBackground ? undefined :  // if it's a background & has a cluster color, make the shadow spread really big
                                     StrCast(this.layoutDoc.boxShadow, ""),
                 borderRadius: StrCast(Doc.Layout(this.layoutDoc).borderRounding),
diff --git a/src/client/views/nodes/DocHolderBox.tsx b/src/client/views/nodes/DocHolderBox.tsx
index 0c4242172..88eb48f51 100644
--- a/src/client/views/nodes/DocHolderBox.tsx
+++ b/src/client/views/nodes/DocHolderBox.tsx
@@ -184,7 +184,7 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent<FieldViewProps, Do
             onContextMenu={this.specificContextMenu}
             onPointerDown={this.onPointerDown} onClick={this.onClick}
             style={{
-                background: this.props.backgroundColor?.(containedDoc),
+                background: this.props.backgroundColor?.(containedDoc, this.props.renderDepth),
                 border: `#00000021 solid ${this.xPad}px`,
                 borderTop: `#0000005e solid ${this.yPad}px`,
                 borderBottom: `#0000005e solid ${this.yPad}px`,
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 47e1b2715..e7427ddc8 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -86,7 +86,7 @@ export interface DocumentViewProps {
     addDocTab: (doc: Doc, where: string, libraryPath?: Doc[]) => boolean;
     pinToPres: (document: Doc) => void;
     backgroundHalo?: () => boolean;
-    backgroundColor?: (doc: Doc) => string | undefined;
+    backgroundColor?: (doc: Doc, renderDepth: number) => string | undefined;
     forcedBackgroundColor?: (doc: Doc) => string | undefined;
     opacity?: () => number | undefined;
     ChromeHeight?: () => number;
@@ -1004,7 +1004,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         if (!(this.props.Document instanceof Doc)) return (null);
         if (GetEffectiveAcl(this.props.Document) === AclPrivate) return (null);
         if (this.props.Document.hidden) return (null);
-        const backgroundColor = Doc.UserDoc().renderStyle === "comic" ? undefined : this.props.forcedBackgroundColor?.(this.Document) || StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document);
+        const backgroundColor = Doc.UserDoc().renderStyle === "comic" ? undefined : this.props.forcedBackgroundColor?.(this.Document) || StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document, this.props.renderDepth);
         const opacity = Cast(this.layoutDoc._opacity, "number", Cast(this.layoutDoc.opacity, "number", Cast(this.Document.opacity, "number", null)));
         const finalOpacity = this.props.opacity ? this.props.opacity() : opacity;
         const finalColor = this.layoutDoc.type === DocumentType.FONTICON || this.layoutDoc._viewType === CollectionViewType.Linear ? undefined : backgroundColor;
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index e631ad5fe..fe0ea80d5 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -38,7 +38,7 @@ export interface FieldViewProps {
     pinToPres: (document: Doc) => void;
     removeDocument?: (document: Doc | Doc[]) => boolean;
     moveDocument?: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean;
-    backgroundColor?: (document: Doc) => string | undefined;
+    backgroundColor?: (document: Doc, renderDepth: number) => string | undefined;
     ScreenToLocalTransform: () => Transform;
     bringToFront: (doc: Doc, sendToBack?: boolean) => void;
     active: (outsideReaction?: boolean) => boolean;
diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx
index a6b1678b5..144defbb0 100644
--- a/src/client/views/nodes/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox.tsx
@@ -61,7 +61,7 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
     render() {
         const label = StrCast(this.rootDoc.label, StrCast(this.rootDoc.title));
         const color = StrCast(this.layoutDoc.color, this._foregroundColor);
-        const backgroundColor = StrCast(this.layoutDoc._backgroundColor, StrCast(this.rootDoc.backgroundColor, this.props.backgroundColor?.(this.rootDoc)));
+        const backgroundColor = StrCast(this.layoutDoc._backgroundColor, StrCast(this.rootDoc.backgroundColor, this.props.backgroundColor?.(this.rootDoc, this.props.renderDepth)));
         const shape = StrCast(this.layoutDoc.iconShape, "round");
         const button = <button className={`menuButton-${shape}`} ref={this._ref} onContextMenu={this.specificContextMenu}
             style={{
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 3f942e87b..532e7dc15 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -17,7 +17,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps, LinkDocument>(
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkBox, fieldKey); }
     render() {
         return <div className={`linkBox-container${this.active() ? "-interactive" : ""}`}
-            style={{ background: this.props.backgroundColor?.(this.props.Document) }} >
+            style={{ background: this.props.backgroundColor?.(this.props.Document, this.props.renderDepth) }} >
 
             <CollectionTreeView {...this.props}
                 ChromeHeight={returnZero}
diff --git a/src/client/views/nodes/MenuIconBox.tsx b/src/client/views/nodes/MenuIconBox.tsx
index 0aa7b327e..5ed8a9b78 100644
--- a/src/client/views/nodes/MenuIconBox.tsx
+++ b/src/client/views/nodes/MenuIconBox.tsx
@@ -19,10 +19,10 @@ export class MenuIconBox extends DocComponent<FieldViewProps, MenuIconDocument>(
 
     render() {
 
-        const color = this.props.backgroundColor?.(this.props.Document) === "lightgrey" ? "black" : "white";
-        const menuBTN = <div className="menuButton" style={{ backgroundColor: this.props.backgroundColor?.(this.props.Document) }}>
+        const color = this.props.backgroundColor?.(this.props.Document, this.props.renderDepth) === "lightgrey" ? "black" : "white";
+        const menuBTN = <div className="menuButton" style={{ backgroundColor: this.props.backgroundColor?.(this.props.Document, this.props.renderDepth) }}>
             <div className="menuButton-wrap"
-                style={{ backgroundColor: this.props.backgroundColor?.(this.props.Document) }} >
+                style={{ backgroundColor: this.props.backgroundColor?.(this.props.Document, this.props.renderDepth) }} >
                 <FontAwesomeIcon className="menuButton-icon" icon={StrCast(this.dataDoc.icon, "user") as any} color={color} size="lg" />
                 <div className="menuButton-label" style={{ color: color }}> {this.dataDoc.title} </div>
             </div>
-- 
cgit v1.2.3-70-g09d2


From 4c4978483c62f9031c7955f5db5e8f15789fcb50 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 11 Aug 2020 11:18:58 -0400
Subject: from last

---
 src/client/util/CurrentUserUtils.ts | 4 ++--
 src/client/util/SettingsManager.tsx | 2 +-
 src/client/views/MainView.tsx       | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'src/client/views/MainView.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 10fdbf534..4fbc27cd3 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -912,8 +912,8 @@ export class CurrentUserUtils {
         doc.fontFamily = StrCast(doc.fontFamily, "Arial");
         doc.fontColor = StrCast(doc.fontColor, "black");
         doc.fontHighlight = StrCast(doc.fontHighlight, "");
-        doc["default-collection-background"] = StrCast(doc["default-collection-background"], "white");
-        doc["default-collection-nested-background"] = Cast(doc["default-collection-nested-background"], "string", null);
+        doc.activeCollectionBackground = StrCast(doc.activeCollectionBackground, "white");
+        doc.activeCollectionNestedBackground = Cast(doc.activeCollectionNestedBackground, "string", null);
         doc.noviceMode = BoolCast(doc.noviceMode, true);
         doc["constants-snapThreshold"] = NumCast(doc["constants-snapThreshold"], 10); //
         doc["constants-dragThreshold"] = NumCast(doc["constants-dragThreshold"], 4); //
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index 737682cf7..ea449e23d 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -56,7 +56,7 @@ export default class SettingsManager extends React.Component<{}> {
     @undoBatch selectUserMode = action((e: React.ChangeEvent) => Doc.UserDoc().noviceMode = (e.currentTarget as any)?.value === "Novice");
     @undoBatch changeFontFamily = action((e: React.ChangeEvent) => Doc.UserDoc().fontFamily = (e.currentTarget as any).value);
     @undoBatch changeFontSize = action((e: React.ChangeEvent) => Doc.UserDoc().fontSize = (e.currentTarget as any).value);
-    @undoBatch switchColor = action((color: ColorState) => Doc.UserDoc()["default-collection-background"] = String(color.hex));
+    @undoBatch switchColor = action((color: ColorState) => Doc.UserDoc().activeCollectionBackground = String(color.hex));
     @undoBatch
     playgroundModeToggle = action(() => {
         this.playgroundMode = !this.playgroundMode;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 3cbc00c92..dbce1502f 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -342,7 +342,7 @@ export class MainView extends React.Component {
                 || doc.title === "Advanced Item Prototypes" || doc.title === "all Creators") {
                 return "lightgrey";
             }
-            return renderDepth > 0 ? StrCast(Doc.UserDoc()["default-collection-nested-background"]) : StrCast(Doc.UserDoc()["default-collection-background"]);
+            return StrCast(renderDepth > 0 ? Doc.UserDoc().activeCollectionNestedBackground : Doc.UserDoc().activeCollectionBackground);
         }
         if (this.darkScheme) {
             switch (doc?.type) {
-- 
cgit v1.2.3-70-g09d2

