From 21aab2fbf28e9cf6d08366b57d368d120d6813bb Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 10 Oct 2019 16:42:12 -0400
Subject: got rid of all CollectionView wrappers around XxxBox's  added
 DocAnnotatableComponent

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

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

diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index 5c1960d53..6251d7114 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -86,7 +86,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
             this.props.parent.drop(e, de);
             e.stopPropagation();
         }
-    })
+    });
 
     getValue = (value: string): any => {
         let parsed = parseInt(value);
-- 
cgit v1.2.3-70-g09d2


From 3afceef2f8c2be1bddf67cecd97086a41ec6dc48 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 11 Oct 2019 16:47:42 -0400
Subject: changes to menu layouts

---
 src/client/documents/Documents.ts                  |   2 +
 src/client/views/GlobalKeyHandler.ts               |  30 +++++-
 src/client/views/Main.tsx                          |   5 -
 src/client/views/MainView.tsx                      | 108 +++++++++++++--------
 .../collections/CollectionMasonryViewFieldRow.tsx  |   2 +-
 .../CollectionStackingViewFieldColumn.tsx          |   4 +-
 src/client/views/nodes/ButtonBox.scss              |   2 +
 src/client/views/nodes/DragBox.tsx                 |   4 +-
 src/client/views/nodes/IconBox.tsx                 |   4 +-
 src/client/views/search/IconBar.tsx                |   2 +-
 src/client/views/search/IconButton.scss            |   2 +-
 .../authentication/models/current_user_utils.ts    |  73 +++++++++++---
 12 files changed, 167 insertions(+), 71 deletions(-)

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

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 7f6ab50d8..6b56fb443 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -74,6 +74,7 @@ export interface DocumentOptions {
     dropAction?: dropActionType;
     backgroundLayout?: string;
     chromeStatus?: string;
+    columnWidth?: number;
     fontSize?: number;
     curPage?: number;
     currentTimecode?: number;
@@ -83,6 +84,7 @@ export interface DocumentOptions {
     dockingConfig?: string;
     autoHeight?: boolean;
     dbDoc?: Doc;
+    icon?: string;
     // [key: string]: Opt<Field>;
 }
 
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 557b3e366..9d239d0bf 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -9,6 +9,7 @@ import { DictationManager } from "../util/DictationManager";
 import SharingManager from "../util/SharingManager";
 import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils";
 import { Cast, PromiseValue } from "../../new_fields/Types";
+import { ScriptField } from "../../new_fields/ScriptField";
 
 const modifiers = ["control", "meta", "shift", "alt"];
 type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise<KeyControlInfo>;
@@ -162,12 +163,31 @@ export default class KeyManager {
                     }
                 }
                 break;
+            case "c":
+                if (MainView.Instance.flyoutWidth > 0) {
+                    MainView.Instance.flyoutWidth = 0;
+                    PromiseValue(Cast(CurrentUserUtils.UserDocument.Library, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
+                } else {
+                    MainView.Instance.flyoutWidth = 400;
+                    PromiseValue(Cast(CurrentUserUtils.UserDocument.Create, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
+                }
+                break;
+            case "l":
+                if (MainView.Instance.flyoutWidth > 0) {
+                    MainView.Instance.flyoutWidth = 0;
+                } else {
+                    MainView.Instance.flyoutWidth = 400;
+                    PromiseValue(Cast(CurrentUserUtils.UserDocument.Library, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
+                }
+                break;
             case "f":
-                stopPropagation = false;
-                preventDefault = false;
-                MainView.Instance.isSearchVisible = !MainView.Instance.isSearchVisible;
-                MainView.Instance.flyoutWidth = MainView.Instance.isSearchVisible ? 400 : 0;
-                PromiseValue(Cast(CurrentUserUtils.UserDocument.searchBox, Doc)).then(pv => pv && (pv.treeViewOpen = (MainView.Instance.flyoutWidth > 0)));
+                if (MainView.Instance.flyoutWidth > 0) {
+                    MainView.Instance.flyoutWidth = 0;
+                    PromiseValue(Cast(CurrentUserUtils.UserDocument.Library, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
+                } else {
+                    MainView.Instance.flyoutWidth = 400;
+                    PromiseValue(Cast(CurrentUserUtils.UserDocument.Search, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
+                }
                 break;
             case "o":
                 let target = SelectionManager.SelectedDocuments()[0];
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 3bd898ac0..a91a2b69e 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -38,11 +38,6 @@ let swapDocs = async () => {
     if (info.id !== "__guest__") {
         // a guest will not have an id registered
         await CurrentUserUtils.loadUserDocument(info);
-        // updates old user documents to prevent chrome on tree view.
-        (await Cast(CurrentUserUtils.UserDocument.workspaces, Doc))!.chromeStatus = "disabled";
-        (await Cast(CurrentUserUtils.UserDocument.recentlyClosed, Doc))!.chromeStatus = "disabled";
-        (await Cast(CurrentUserUtils.UserDocument.sidebar, Doc))!.chromeStatus = "disabled";
-        CurrentUserUtils.UserDocument.chromeStatus = "disabled";
         await swapDocs();
     }
     document.getElementById('root')!.addEventListener('wheel', event => {
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 1ec21f638..6f60de1c4 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -15,7 +15,7 @@ import { listSpec } from '../../new_fields/Schema';
 import { BoolCast, Cast, FieldValue, StrCast, PromiseValue } from '../../new_fields/Types';
 import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
 import { RouteStore } from '../../server/RouteStore';
-import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils } from '../../Utils';
+import { emptyFunction, returnEmptyString, returnOne, returnTrue, returnFalse, Utils } from '../../Utils';
 import { DocServer } from '../DocServer';
 import { Docs, DocumentOptions } from '../documents/Documents';
 import { ClientUtils } from '../util/ClientUtils';
@@ -40,6 +40,8 @@ import { PreviewCursor } from './PreviewCursor';
 import { FilterBox } from './search/FilterBox';
 import { OverlayView } from './OverlayView';
 import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager';
+import { CollectionStackingView } from './collections/CollectionStackingView';
+import { ScriptField } from '../../new_fields/ScriptField';
 
 @observer
 export class MainView extends React.Component {
@@ -459,33 +461,63 @@ export class MainView extends React.Component {
     @computed
     get flyout() {
         let sidebar: FieldResult<Field>;
-        if (!this.userDoc || !((sidebar = this.userDoc.sidebar) instanceof Doc)) {
+        if (!this.userDoc || !((sidebar = this.userDoc.sidebarContainer) instanceof Doc)) {
             return (null);
         }
-        return <DocumentView
-            Document={this.isSearchVisible ? Cast(CurrentUserUtils.UserDocument.searchBox, Doc) as Doc : sidebar}
-            DataDoc={undefined}
-            addDocument={undefined}
-            addDocTab={this.addDocTabFunc}
-            pinToPres={emptyFunction}
-            removeDocument={undefined}
-            ruleProvider={undefined}
-            onClick={undefined}
-            ScreenToLocalTransform={Transform.Identity}
-            ContentScaling={returnOne}
-            PanelWidth={this.flyoutWidthFunc}
-            PanelHeight={this.getPHeight}
-            renderDepth={0}
-            focus={emptyFunction}
-            backgroundColor={returnEmptyString}
-            parentActive={returnTrue}
-            whenActiveChanged={emptyFunction}
-            bringToFront={emptyFunction}
-            ContainingCollectionView={undefined}
-            ContainingCollectionDoc={undefined}
-            zoomToScale={emptyFunction}
-            getScale={returnOne}>
-        </DocumentView>;
+        (Cast(CurrentUserUtils.UserDocument.libraryButtons, Doc) as Doc).columnWidth = this.flyoutWidthFunc() / 3 - 30;
+        return <div style={{ display: "flex", flexDirection: "column", position: "absolute", width: "100%", height: "100%" }}>
+            <div style={{ position: "relative", height: "85px", width: "100%" }}>
+                <DocumentView
+                    Document={Cast(CurrentUserUtils.UserDocument.libraryButtons, Doc) as Doc}
+                    DataDoc={undefined}
+                    addDocument={undefined}
+                    addDocTab={this.addDocTabFunc}
+                    pinToPres={emptyFunction}
+                    removeDocument={undefined}
+                    ruleProvider={undefined}
+                    onClick={undefined}
+                    ScreenToLocalTransform={Transform.Identity}
+                    ContentScaling={returnOne}
+                    PanelWidth={this.flyoutWidthFunc}
+                    PanelHeight={this.getPHeight}
+                    renderDepth={0}
+                    focus={emptyFunction}
+                    backgroundColor={returnEmptyString}
+                    parentActive={returnTrue}
+                    whenActiveChanged={emptyFunction}
+                    bringToFront={emptyFunction}
+                    ContainingCollectionView={undefined}
+                    ContainingCollectionDoc={undefined}
+                    zoomToScale={emptyFunction}
+                    getScale={returnOne}>
+                </DocumentView>
+            </div>
+            <div style={{ position: "relative", height: "calc(100% - 80px)", width: "100%" }}>
+                <DocumentView
+                    Document={this.isSearchVisible ? Cast(CurrentUserUtils.UserDocument.searchBox, Doc) as Doc : sidebar}
+                    DataDoc={undefined}
+                    addDocument={undefined}
+                    addDocTab={this.addDocTabFunc}
+                    pinToPres={emptyFunction}
+                    removeDocument={undefined}
+                    ruleProvider={undefined}
+                    onClick={undefined}
+                    ScreenToLocalTransform={Transform.Identity}
+                    ContentScaling={returnOne}
+                    PanelWidth={this.flyoutWidthFunc}
+                    PanelHeight={this.getPHeight}
+                    renderDepth={0}
+                    focus={emptyFunction}
+                    backgroundColor={returnEmptyString}
+                    parentActive={returnTrue}
+                    whenActiveChanged={emptyFunction}
+                    bringToFront={emptyFunction}
+                    ContainingCollectionView={undefined}
+                    ContainingCollectionDoc={undefined}
+                    zoomToScale={emptyFunction}
+                    getScale={returnOne}>
+                </DocumentView>
+            </div></div>;
     }
 
     @computed
@@ -493,7 +525,7 @@ export class MainView extends React.Component {
         if (!this.userDoc) {
             return (<div>{this.dockingContent}</div>);
         }
-        let sidebar = this.userDoc.sidebar;
+        let sidebar = this.userDoc.sidebarContainer;
         if (!(sidebar instanceof Doc)) {
             return (null);
         }
@@ -585,16 +617,16 @@ export class MainView extends React.Component {
         // let googlePhotosSearch = () => GooglePhotosClientUtils.CollectionFromSearch(Docs.Create.MasonryDocument, { included: [GooglePhotosClientUtils.ContentCategories.LANDSCAPES] });
 
         let btns: [React.RefObject<HTMLDivElement>, IconName, string, () => Doc | Promise<Doc>][] = [
-            [React.createRef<HTMLDivElement>(), "object-group", "Add Collection", addColNode],
-            [React.createRef<HTMLDivElement>(), "tv", "Add Presentation Trail", addPresNode],
-            [React.createRef<HTMLDivElement>(), "globe-asia", "Add Website", addWebNode],
-            [React.createRef<HTMLDivElement>(), "bolt", "Add Button", addButtonDocument],
-            [React.createRef<HTMLDivElement>(), "file", "Add Document Dragger", addDragboxNode],
+            //[React.createRef<HTMLDivElement>(), "object-group", "Add Collection", addColNode],
+            //[React.createRef<HTMLDivElement>(), "tv", "Add Presentation Trail", addPresNode],
+            //[React.createRef<HTMLDivElement>(), "globe-asia", "Add Website", addWebNode],
+            //[React.createRef<HTMLDivElement>(), "bolt", "Add Button", addButtonDocument],
+            //[React.createRef<HTMLDivElement>(), "file", "Add Document Dragger", addDragboxNode],
             // [React.createRef<HTMLDivElement>(), "object-group", "Test Google Photos Search", googlePhotosSearch],
-            [React.createRef<HTMLDivElement>(), "cloud-upload-alt", "Import Directory", addImportCollectionNode], //remove at some point in favor of addImportCollectionNode
+            //[React.createRef<HTMLDivElement>(), "cloud-upload-alt", "Import Directory", addImportCollectionNode], //remove at some point in favor of addImportCollectionNode
             //[React.createRef<HTMLDivElement>(), "play", "Add Youtube Searcher", addYoutubeSearcher],
         ];
-        if (!ClientUtils.RELEASE) btns.unshift([React.createRef<HTMLDivElement>(), "cat", "Add Cat Image", addImageNode]);
+        //if (!ClientUtils.RELEASE) btns.unshift([React.createRef<HTMLDivElement>(), "cat", "Add Cat Image", addImageNode]);
 
         return < div id="add-nodes-menu" style={{ left: (this.flyoutTranslate ? this.flyoutWidth : 0) + 20, bottom: 20 }} >
 
@@ -603,7 +635,7 @@ export class MainView extends React.Component {
 
             <div id="add-options-content">
                 <ul id="add-options-list">
-                    <li key="search"><button className="add-button round-button" title="Search" onClick={this.toggleSearch}><FontAwesomeIcon icon="search" size="sm" /></button></li>
+                    {/* <li key="search"><button className="add-button round-button" title="Search" onClick={this.toggleSearch}><FontAwesomeIcon icon="search" size="sm" /></button></li> */}
                     <li key="undo"><button className="add-button round-button" title="Undo" style={{ opacity: UndoManager.CanUndo() ? 1 : 0.5, transition: "0.4s ease all" }} onClick={() => UndoManager.Undo()}><FontAwesomeIcon icon="undo-alt" size="sm" /></button></li>
                     <li key="redo"><button className="add-button round-button" title="Redo" style={{ opacity: UndoManager.CanRedo() ? 1 : 0.5, transition: "0.4s ease all" }} onClick={() => UndoManager.Redo()}><FontAwesomeIcon icon="redo-alt" size="sm" /></button></li>
                     {btns.map(btn =>
@@ -612,7 +644,7 @@ export class MainView extends React.Component {
                                 <FontAwesomeIcon icon={btn[1]} size="sm" />
                             </button>
                         </div></li>)}
-                    <li key="undoTest"><button className="add-button round-button" title="Click if undo isn't working" onClick={() => UndoManager.TraceOpenBatches()}><FontAwesomeIcon icon="exclamation" size="sm" /></button></li>
+                    {/* <li key="undoTest"><button className="add-button round-button" title="Click if undo isn't working" onClick={() => UndoManager.TraceOpenBatches()}><FontAwesomeIcon icon="exclamation" size="sm" /></button></li> */}
                     <li key="color"><button className="add-button round-button" title="Select Color" style={{ zIndex: 1000 }} onClick={() => this.toggleColorPicker()}><div className="toolbar-color-button" style={{ backgroundColor: InkingControl.Instance.selectedColor }} >
                         <div className="toolbar-color-picker" onClick={this.onColorClick} style={this._colorPickerDisplay ? { color: "black", display: "block" } : { color: "black", display: "none" }}>
                             <SketchPicker color={InkingControl.Instance.selectedColor} onChange={InkingControl.Instance.switchColor} />
@@ -648,9 +680,7 @@ export class MainView extends React.Component {
     @observable isSearchVisible = false;
     @action.bound
     toggleSearch = () => {
-        this.isSearchVisible = !MainView.Instance.isSearchVisible;
-        MainView.Instance.flyoutWidth = MainView.Instance.isSearchVisible ? 400 : 0;
-        PromiseValue(Cast(CurrentUserUtils.UserDocument.searchBox, Doc)).then(pv => pv && (pv.treeViewOpen = (MainView.Instance.flyoutWidth > 0)));
+        PromiseValue(Cast(CurrentUserUtils.UserDocument.Search, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv }));
     }
 
     @computed private get dictationOverlay() {
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index 6251d7114..1709b9c99 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -353,7 +353,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr
             </div > : (null);
         const background = this._background; //to account for observables in Measure
         const collapsed = this.collapsed;
-        let chromeStatus = this.props.parent.props.ContainingCollectionDoc && this.props.parent.props.ContainingCollectionDoc.chromeStatus;
+        let chromeStatus = this.props.parent.props.Document.chromeStatus;
         return (
             <Measure offset onResize={this.handleResize}>
                 {({ measureRef }) => {
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 815b28586..7e54b0f29 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -335,11 +335,11 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
                 </div>
             </div> : (null);
         for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth / style.numGroupColumns}px `;
-        let chromeStatus = this.props.parent.props.ContainingCollectionDoc && this.props.parent.props.ContainingCollectionDoc.chromeStatus;
+        let chromeStatus = this.props.parent.props.Document.chromeStatus;
         return (
             <div className="collectionStackingViewFieldColumn" key={heading} style={{ width: `${100 / ((uniqueHeadings.length + ((chromeStatus !== 'view-mode' && chromeStatus !== 'disabled') ? 1 : 0)) || 1)}%`, background: this._background }}
                 ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}>
-                {headingView}
+                {this.props.parent.Document.hideHeadings ? (null) : headingView}
                 {
                     this.collapsed ? (null) :
                         <div>
diff --git a/src/client/views/nodes/ButtonBox.scss b/src/client/views/nodes/ButtonBox.scss
index 75a790667..e8a3d1479 100644
--- a/src/client/views/nodes/ButtonBox.scss
+++ b/src/client/views/nodes/ButtonBox.scss
@@ -13,6 +13,8 @@
     border-radius: inherit;
     text-align: center;
     display: table;
+    overflow: hidden;
+    text-overflow: ellipsis;
 }
 .buttonBox-mainButtonCenter {
     height: 100%;
diff --git a/src/client/views/nodes/DragBox.tsx b/src/client/views/nodes/DragBox.tsx
index 6c3db18c4..8429382e3 100644
--- a/src/client/views/nodes/DragBox.tsx
+++ b/src/client/views/nodes/DragBox.tsx
@@ -52,7 +52,7 @@ export class DragBox extends DocComponent<FieldViewProps, DragDocument>(DragDocu
             e.stopPropagation();
             e.preventDefault();
             let res = onDragStart && onDragStart.script.run({ this: this.props.Document }).result;
-            let doc = (res as Doc) ||  Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" });
+            let doc = (res as Doc) || Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" });
             DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY);
         }
         e.stopPropagation();
@@ -93,7 +93,7 @@ export class DragBox extends DocComponent<FieldViewProps, DragDocument>(DragDocu
 
     render() {
         return (<div className="dragBox-outerDiv" onContextMenu={this.onContextMenu} onPointerDown={this.onDragStart} ref={this._mainCont}>
-            <FontAwesomeIcon className="dragBox-icon" icon="folder" size="lg" color="white" />
+            <FontAwesomeIcon className="dragBox-icon" icon={this.props.Document.icon as any} size="lg" color="white" />
         </div>);
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx
index f3adade58..4971f61b7 100644
--- a/src/client/views/nodes/IconBox.tsx
+++ b/src/client/views/nodes/IconBox.tsx
@@ -26,6 +26,8 @@ library.add(faFilm, faTag, faTextHeight);
 export class IconBox extends React.Component<FieldViewProps> {
     public static LayoutString() { return FieldView.LayoutString(IconBox); }
 
+    @observable _panelWidth: number = 0;
+    @observable _panelHeight: number = 0;
     @computed get layout(): string { const field = Cast(this.props.Document[this.props.fieldKey], IconField); return field ? field.icon : "<p>Error loading icon data</p>"; }
     @computed get minimizedIcon() { return IconBox.DocumentIcon(this.layout); }
 
@@ -69,8 +71,6 @@ export class IconBox extends React.Component<FieldViewProps> {
             cm.addItem({ description: "Use Target Title", event: () => IconBox.AutomaticTitle(this.props.Document), icon: "text-height" });
         }
     }
-    @observable _panelWidth: number = 0;
-    @observable _panelHeight: number = 0;
     render() {
         let label = this.props.Document.hideLabel ? "" : this.props.Document.title;
         return (
diff --git a/src/client/views/search/IconBar.tsx b/src/client/views/search/IconBar.tsx
index bdeb57d5c..cff397407 100644
--- a/src/client/views/search/IconBar.tsx
+++ b/src/client/views/search/IconBar.tsx
@@ -60,7 +60,7 @@ export class IconBar extends React.Component {
         return (
             <div className="icon-bar">
                 {FilterBox.Instance._allIcons.map((type: string) =>
-                    <IconButton type={type} />
+                    <IconButton key={type.toString()} type={type} />
                 )}
             </div>
         );
diff --git a/src/client/views/search/IconButton.scss b/src/client/views/search/IconButton.scss
index d1853177e..4a3107676 100644
--- a/src/client/views/search/IconButton.scss
+++ b/src/client/views/search/IconButton.scss
@@ -35,7 +35,7 @@
         text-align: center;
         height: 15px;
         margin-top: 5px;
-        opacity: 0;
+        opacity: 1;
         -webkit-transition: all 0.2s ease-in-out;
         -moz-transition: all 0.2s ease-in-out;
         -o-transition: all 0.2s ease-in-out;
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index f9e3dc479..e1bb91838 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -12,6 +12,7 @@ import { listSpec } from "../../../new_fields/Schema";
 import { Cast, StrCast, PromiseValue } from "../../../new_fields/Types";
 import { Utils } from "../../../Utils";
 import { RouteStore } from "../../RouteStore";
+import { ScriptField } from "../../../new_fields/ScriptField";
 
 export class CurrentUserUtils {
     private static curr_id: string;
@@ -97,24 +98,70 @@ export class CurrentUserUtils {
             curPresentation.boxShadow = "0 0";
             doc.curPresentation = curPresentation;
         }
-        if (doc.searchBox === undefined) {
+
+        if (doc.Library === undefined) {
+            let Search = Docs.Create.ButtonDocument({ width: 50, height: 35, title: "Search" });
+            let Library = Docs.Create.ButtonDocument({ width: 50, height: 35, title: "Library" });
+            let Create = Docs.Create.ButtonDocument({ width: 35, height: 35, title: "Create" });
+            if (doc.sidebarContainer === undefined) {
+                doc.sidebarContainer = new Doc();
+                (doc.sidebarContainer as Doc).chromeStatus = "disabled";
+            }
+
+            const library = Docs.Create.TreeDocument([doc.workspaces as Doc, doc, doc.recentlyClosed as Doc], { title: "Library" });
+            library.forceActive = true;
+            library.lockedPosition = true;
+            library.gridGap = 5;
+            library.xMargin = 5;
+            library.yMargin = 5;
+            library.boxShadow = "1 1 3";
+            library.workspaceLibrary = true; // flag that this is the document that shows the Notifications button when documents are shared
+            Library.targetContainer = doc.sidebarContainer;
+            Library.library = library;
+            Library.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.library");
+
             const searchBox = Docs.Create.QueryDocument({ title: "Searching" });
             searchBox.boxShadow = "0 0";
             searchBox.ignoreClick = true;
-            doc.searchBox = searchBox;
-        }
+            Search.searchBox = searchBox;
+            Search.targetContainer = doc.sidebarContainer;
+            Search.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.searchBox");
 
-        if (doc.sidebar === undefined) {
-            const sidebar = Docs.Create.TreeDocument([doc.workspaces as Doc, doc, doc.recentlyClosed as Doc], { title: "Sidebar" });
-            sidebar.forceActive = true;
-            sidebar.lockedPosition = true;
-            sidebar.gridGap = 5;
-            sidebar.xMargin = 5;
-            sidebar.yMargin = 5;
-            sidebar.boxShadow = "1 1 3";
-            sidebar.workspaceLibrary = true; // flag that this is the document that shows the Notifications button when documents are shared
-            doc.sidebar = sidebar;
+            let createCollection = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Collection", icon: "folder" });
+            let createWebPage = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Web Page", icon: "globe-asia" });
+            createWebPage.onDragStart = ScriptField.MakeFunction('Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })');
+            let createCatImage = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Image", icon: "cat" });
+            createCatImage.onDragStart = ScriptField.MakeFunction('Docs.Create.ImageDocument(imgurl, { width: 200, title: "an image of a cat" })');
+            let createButton = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Button", icon: "bolt" });
+            createButton.onDragStart = ScriptField.MakeFunction('Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })');
+            let createPresentation = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Presentation", icon: "tv" });
+            createPresentation.onDragStart = ScriptField.MakeFunction('Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List<Doc>(), { width: 200, height: 500, title: "a presentation trail" })');
+            let createFolderImport = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Import Folder", icon: "cloud-upload-alt" });
+            createFolderImport.onDragStart = ScriptField.MakeFunction('Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })');
+            const creators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, height: 50, columnWidth: 35, chromeStatus: "disabled", title: "buttons" });
+            Create.targetContainer = doc.sidebarContainer;
+            Create.creators = creators;
+            Create.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.creators");
+
+            const buttons = Docs.Create.StackingDocument([Search, Library, Create], { width: 500, height: 80, chromeStatus: "disabled", title: "buttons" });
+            buttons.sectionFilter = "title";
+            buttons.boxShadow = "0 0";
+            buttons.ignoreClick = true;
+            buttons.hideHeadings = true;
+            doc.libraryButtons = buttons;
+
+            doc.Library = Library;
+            doc.Create = Create;
+            doc.Search = Search;
+            (Library.onClick as ScriptField).script.run({ this: Library });
+            //(doc.sidebarContainer as Doc).proto = library;
         }
+        PromiseValue(Cast(doc.libraryButtons, Doc)).then(libraryButtons => {
+            if (libraryButtons) {
+                libraryButtons.backgroundColor = "lightgrey";
+            }
+        });
+
         PromiseValue(Cast(doc.sidebar, Doc)).then(sidebar => {
             if (sidebar) {
                 sidebar.backgroundColor = "lightgrey";
-- 
cgit v1.2.3-70-g09d2


From cf6949fd114c2619caeaeda0652b1f3a36a69d99 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 21 Oct 2019 01:31:29 -0400
Subject: start of ImageBox cleanup

---
 .../views/collections/CollectionBaseView.tsx       |   8 +-
 .../collections/CollectionMasonryViewFieldRow.tsx  |   9 +-
 src/client/views/nodes/ImageBox.scss               |   5 +
 src/client/views/nodes/ImageBox.tsx                | 113 +++------------------
 4 files changed, 27 insertions(+), 108 deletions(-)

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

diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 15853fcae..c46648ac1 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -1,18 +1,16 @@
 import { action, computed, observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
+import { DateField } from '../../../new_fields/DateField';
 import { Doc, DocListCast } from '../../../new_fields/Doc';
-import { Id } from '../../../new_fields/FieldSymbols';
-import { List } from '../../../new_fields/List';
 import { listSpec } from '../../../new_fields/Schema';
-import { BoolCast, Cast, NumCast, PromiseValue, StrCast, FieldValue } from '../../../new_fields/Types';
+import { BoolCast, Cast, FieldValue, PromiseValue, StrCast } from '../../../new_fields/Types';
+import { ImageField } from '../../../new_fields/URLField';
 import { DocumentManager } from '../../util/DocumentManager';
 import { SelectionManager } from '../../util/SelectionManager';
 import { ContextMenu } from '../ContextMenu';
 import { FieldViewProps } from '../nodes/FieldView';
 import './CollectionBaseView.scss';
-import { DateField } from '../../../new_fields/DateField';
-import { ImageField } from '../../../new_fields/URLField';
 
 export enum CollectionViewType {
     Invalid,
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index 1709b9c99..4259e948b 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
@@ -4,12 +4,12 @@ import { faPalette } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action, observable } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, WidthSym } from "../../../new_fields/Doc";
-import { Id } from "../../../new_fields/FieldSymbols";
+import Measure from "react-measure";
+import { Doc } from "../../../new_fields/Doc";
 import { PastelSchemaPalette, SchemaHeaderField } from "../../../new_fields/SchemaHeaderField";
 import { ScriptField } from "../../../new_fields/ScriptField";
-import { NumCast, StrCast } from "../../../new_fields/Types";
-import { Utils, numberRange } from "../../../Utils";
+import { StrCast } from "../../../new_fields/Types";
+import { numberRange } from "../../../Utils";
 import { Docs } from "../../documents/Documents";
 import { DragManager } from "../../util/DragManager";
 import { CompileScript } from "../../util/Scripting";
@@ -20,7 +20,6 @@ import { anchorPoints, Flyout } from "../DocumentDecorations";
 import { EditableView } from "../EditableView";
 import { CollectionStackingView } from "./CollectionStackingView";
 import "./CollectionStackingView.scss";
-import Measure from "react-measure";
 
 library.add(faPalette);
 
diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss
index c5265556e..57c024bbf 100644
--- a/src/client/views/nodes/ImageBox.scss
+++ b/src/client/views/nodes/ImageBox.scss
@@ -7,6 +7,7 @@
     max-width: 100%;
     max-height: 100%;
     pointer-events: none;
+    background:transparent;
 }
 
 .imageBox-container {
@@ -52,6 +53,10 @@
     padding: 3px;
     background: white;
     cursor: pointer;
+    opacity:0.15;
+}
+#google-photos:hover{
+    opacity: 1;
 }
 
 #google-tags {
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index ff129cf1d..fbf05d148 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -57,29 +57,16 @@ const ImageDocument = makeInterface(pageSchema, documentSchema);
 
 @observer
 export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocument>(ImageDocument) {
-
     public static LayoutString(fieldExt?: string) { return FieldView.LayoutString(ImageBox, "data", fieldExt); }
-    @observable static _showControls: boolean;
     private _imgRef: React.RefObject<HTMLImageElement> = React.createRef();
-    private _downX: number = 0;
-    private _downY: number = 0;
-    private _lastTap: number = 0;
+    private _dropDisposer?: DragManager.DragDropDisposer;
     @observable private _isOpen: boolean = false;
-    private dropDisposer?: DragManager.DragDropDisposer;
-    @observable private hoverActive = false;
+    @observable private _audioState = 0;
+    @observable static _showControls: boolean;
 
     protected createDropTarget = (ele: HTMLDivElement) => {
-        if (this.dropDisposer) {
-            this.dropDisposer();
-        }
-        if (ele) {
-            this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } });
-        }
-    }
-    onDrop = (e: React.DragEvent) => {
-        e.stopPropagation();
-        e.preventDefault();
-        console.log("IMPLEMENT ME PLEASE");
+        this._dropDisposer && this._dropDisposer();
+        ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }));
     }
 
     @undoBatch
@@ -97,29 +84,6 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
         }
     }
 
-    onPointerDown = (e: React.PointerEvent): void => {
-        if (e.shiftKey && e.ctrlKey) {
-            e.stopPropagation(); // allows default system drag drop of images with shift+ctrl only
-        }
-        // if (Date.now() - this._lastTap < 300) {
-        //     if (e.buttons === 1) {
-        //         this._downX = e.clientX;
-        //         this._downY = e.clientY;
-        //         document.removeEventListener("pointerup", this.onPointerUp);
-        //         document.addEventListener("pointerup", this.onPointerUp);
-        //     }
-        // } else {
-        //     this._lastTap = Date.now();
-        // }
-    }
-    @action
-    onPointerUp = (e: PointerEvent): void => {
-        document.removeEventListener("pointerup", this.onPointerUp);
-        if (Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2) {
-            this._isOpen = true;
-        }
-        e.stopPropagation();
-    }
 
     @action
     lightbox = (images: string[]) => {
@@ -193,12 +157,10 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
     });
 
     specificContextMenu = (e: React.MouseEvent): void => {
-        let field = Cast(this.Document[this.props.fieldKey], ImageField);
+        const field = Cast(this.Document[this.props.fieldKey], ImageField);
         if (field) {
-            let url = field.url.href;
             let funcs: ContextMenuProps[] = [];
-            funcs.push({ description: "Copy path", event: () => Utils.CopyText(url), icon: "expand-arrows-alt" });
-            funcs.push({ description: "Record 1sec audio", event: this.recordAudioAnnotation, icon: "expand-arrows-alt" });
+            funcs.push({ description: "Copy path", event: () => Utils.CopyText(field.url.href), icon: "expand-arrows-alt" });
             funcs.push({ description: "Rotate", event: this.rotate, icon: "expand-arrows-alt" });
 
             let existingAnalyze = ContextMenu.Instance.findByDescription("Analyzers...");
@@ -214,12 +176,10 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
     extractFaces = () => {
         let converter = (results: any) => {
             let faceDocs = new List<Doc>();
-            results.map((face: CognitiveServices.Image.Face) => faceDocs.push(Docs.Get.DocumentHierarchyFromJson(face, `Face: ${face.faceId}`)!));
+            results.reduce((face: CognitiveServices.Image.Face, faceDocs: List<Doc>) => faceDocs.push(Docs.Get.DocumentHierarchyFromJson(face, `Face: ${face.faceId}`)!), new List<Doc>());
             return faceDocs;
         };
-        if (this.url) {
-            CognitiveServices.Image.Appliers.ProcessImage(this.extensionDoc, ["faces"], this.url, Service.Face, converter);
-        }
+        this.url && CognitiveServices.Image.Appliers.ProcessImage(this.extensionDoc, ["faces"], this.url, Service.Face, converter);
     }
 
     generateMetadata = (threshold: Confidence = Confidence.Excellent) => {
@@ -236,31 +196,14 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
             tagDoc.confidence = threshold;
             return tagDoc;
         };
-        if (this.url) {
-            CognitiveServices.Image.Appliers.ProcessImage(this.extensionDoc, ["generatedTagsDoc"], this.url, Service.ComputerVision, converter);
-        }
+        this.url && CognitiveServices.Image.Appliers.ProcessImage(this.extensionDoc, ["generatedTagsDoc"], this.url, Service.ComputerVision, converter);
     }
 
-    @action
-    onDotDown(index: number) {
-        this.Document.curPage = index;
-    }
     @computed private get url() {
-        let data = Cast(Doc.GetProto(this.props.Document)[this.props.fieldKey], ImageField);
+        let data = Cast(this.dataDoc[this.props.fieldKey], ImageField);
         return data ? data.url.href : undefined;
     }
 
-    dots(paths: string[]) {
-        let nativeWidth = (this.Document.nativeWidth || 1);
-        let dist = Math.min(nativeWidth / paths.length, 40);
-        let left = (nativeWidth - paths.length * dist) / 2;
-        return paths.map((p, i) =>
-            <div className="imageBox-placer" key={i} >
-                <div className="imageBox-dot" style={{ background: (i === this.Document.curPage ? "black" : "gray"), transform: `translate(${i * dist + left}px, 0px)` }} onPointerDown={(e: React.PointerEvent) => { e.stopPropagation(); this.onDotDown(i); }} />
-            </div>
-        );
-    }
-
     choosePath(url: URL) {
         const lower = url.href.toLowerCase();
         if (url.protocol === "data") {
@@ -305,13 +248,9 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
                     }), 0);
                 }
             })
-            .catch((err: any) => {
-                console.log(err);
-            });
+            .catch((err: any) => console.log(err));
     }
 
-    @observable _audioState = 0;
-
     @action
     onPointerEnter = () => {
         let self = this;
@@ -330,20 +269,6 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
             });
             this._audioState = 1;
         }
-        // else {
-        //     if (this._audioState === 0) {
-        //         this._audioState = 1;
-        //         new Howl({
-        //             src: ["https://www.kozco.com/tech/piano2-CoolEdit.mp3"],
-        //             autoplay: true,
-        //             loop: false,
-        //             volume: 0.5,
-        //             onend: function () {
-        //                 runInAction(() => self._audioState = 0);
-        //             }
-        //         });
-        //     }
-        // }
     }
 
     audioDown = () => this.recordAudioAnnotation();
@@ -353,7 +278,6 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
         return !remoteUrl ? (null) : (<img
             id={"google-photos"}
             src={"/assets/google_photos.png"}
-            style={{ opacity: this.hoverActive ? 1 : 0 }}
             onClick={() => window.open(remoteUrl)}
         />);
     }
@@ -364,7 +288,6 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
     }
 
     @computed get content() {
-        console.log("REDOING IMAGE CONTENT");
         // let transform = this.props.ScreenToLocalTransform().inverse();
         let pw = typeof this.props.PanelWidth === "function" ? this.props.PanelWidth() : typeof this.props.PanelWidth === "number" ? (this.props.PanelWidth as any) as number : 50;
         // var [sptX, sptY] = transform.transformPoint(0, 0);
@@ -389,17 +312,14 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
         let rotation = NumCast(this.Document.rotation, 0);
         let aspect = (rotation % 180) ? this.Document[HeightSym]() / this.Document[WidthSym]() : 1;
         let shift = (rotation % 180) ? (nativeHeight - nativeWidth / aspect) / 2 : 0;
-        let srcpath = paths[Math.min(paths.length - 1, NumCast(this.Document.curPage))];
+        let srcpath = paths[Math.min(paths.length - 1, (this.Document.curPage || 0))];
         let fadepath = paths[Math.min(paths.length - 1, 1)];
 
         !this.Document.ignoreAspect && this.resize(srcpath);
 
         return (
-            <div className={`imageBox-cont${interactive}`} style={{ background: "transparent" }}
-                onPointerDown={this.onPointerDown}
-                onPointerEnter={action(() => this.hoverActive = true)}
-                onPointerLeave={action(() => this.hoverActive = false)}
-                onDrop={this.onDrop} ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
+            <div className={`imageBox-cont${interactive}`}
+                ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
                 <div id="cf">
                     <img
                         key={this._smallRetryCount + (this._mediumRetryCount << 4) + (this._largeRetryCount << 8)} // force cache to update on retrys
@@ -416,7 +336,6 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
                         ref={this._imgRef}
                         onError={this.onError} /></div>}
                 </div>
-                {paths.length > 1 ? this.dots(paths) : (null)}
                 <div className="imageBox-audioBackground"
                     onPointerDown={this.audioDown}
                     onPointerEnter={this.onPointerEnter}
@@ -426,13 +345,11 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
                         style={{ color: [DocListCast(this.extensionDoc.audioAnnotations).length ? "blue" : "gray", "green", "red"][this._audioState] }} icon={faFileAudio} size="sm" />
                 </div>
                 {this.considerGooglePhotosLink()}
-                {/* {this.lightbox(paths)} */}
                 <FaceRectangles document={this.extensionDoc} color={"#0000FF"} backgroundColor={"#0000FF"} />
             </div>);
     }
 
     render() {
-        trace();
         if (!Doc.UpdateDocumentExtensionForField(this.dataDoc, this.props.fieldKey)) return (null);
         return (<div className={"imageBox-container"} onContextMenu={this.specificContextMenu}>
             <CollectionFreeFormView {...this.props}
-- 
cgit v1.2.3-70-g09d2

