From 5454385b6fabbcafee4d797829fb9ceaa8a71ed1 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 25 Jul 2020 20:14:16 -0400
Subject: made buttons turn into fonticons on iconify.  droppin fonticons onto
 linear views keeps them as buttons.  droppin buttons on linear view makes
 them fonticons. fixed ColletionMenu scripts to work with templates by usin
 self instead of this. fixed pointer events with text boxes for filterview &
 normal.  fixed fieldKey deletin and addin

---
 src/client/views/collections/CollectionMenu.tsx | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

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

diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 992c1f600..81c349b26 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -2,7 +2,7 @@ import React = require("react");
 import { FontAwesomeIcon, FontAwesomeIconProps } from "@fortawesome/react-fontawesome";
 import { action, computed, observable, reaction, runInAction, Lambda } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, DocListCast, Opt } from "../../../fields/Doc";
+import { Doc, DocListCast, Opt, Field } from "../../../fields/Doc";
 import { BoolCast, Cast, StrCast, NumCast } from "../../../fields/Types";
 import AntimodeMenu from "../AntimodeMenu";
 import "./CollectionMenu.scss";
@@ -24,6 +24,7 @@ import { Document } from "../../../fields/documentSchemas";
 import { SelectionManager } from "../../util/SelectionManager";
 import { DocumentView } from "../nodes/DocumentView";
 import { ColorState } from "react-color";
+import { ObjectField } from "../../../fields/ObjectField";
 
 @observer
 export default class CollectionMenu extends AntimodeMenu {
@@ -72,42 +73,48 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
     get target() { return this.props.CollectionView.props.Document; }
     _templateCommand = {
         params: ["target", "source"], title: "item view",
-        script: "this.target.childLayoutTemplate = getDocTemplate(this.source?.[0])",
+        script: "self.target.childLayoutTemplate = getDocTemplate(self.source?.[0])",
         immediate: undoBatch((source: Doc[]) => source.length && (this.target.childLayoutTemplate = Doc.getDocTemplate(source?.[0]))),
         initialize: emptyFunction,
     };
     _narrativeCommand = {
         params: ["target", "source"], title: "child click view",
-        script: "this.target.childClickedOpenTemplateView = getDocTemplate(this.source?.[0])",
+        script: "self.target.childClickedOpenTemplateView = getDocTemplate(self.source?.[0])",
         immediate: undoBatch((source: Doc[]) => source.length && (this.target.childClickedOpenTemplateView = Doc.getDocTemplate(source?.[0]))),
         initialize: emptyFunction,
     };
     _contentCommand = {
         params: ["target", "source"], title: "clear content",
-        script: "getProto(this.target).data = copyField(this.source);",
+        script: "getProto(self.target).data = copyField(self.source);",
         immediate: undoBatch((source: Doc[]) => Doc.GetProto(this.target).data = new List<Doc>(source)), // Doc.aliasDocs(source),
         initialize: emptyFunction,
     };
     _viewCommand = {
         params: ["target"], title: "bookmark view",
-        script: "this.target._panX = this['target-panX']; this.target._panY = this['target-panY']; this.target._viewScale = this['target-viewScale'];",
+        script: "self.target._panX = self['target-panX']; self.target._panY = self['target-panY']; self.target._viewScale = self['target-viewScale'];",
         immediate: undoBatch((source: Doc[]) => { this.target._panX = 0; this.target._panY = 0; this.target._viewScale = 1; }),
         initialize: (button: Doc) => { button['target-panX'] = this.target._panX; button['target-panY'] = this.target._panY; button['target-viewScale'] = this.target._viewScale; },
     };
     _clusterCommand = {
         params: ["target"], title: "fit content",
-        script: "this.target._fitToBox = !this.target._fitToBox;",
+        script: "self.target._fitToBox = !self.target._fitToBox;",
         immediate: undoBatch((source: Doc[]) => this.target._fitToBox = !this.target._fitToBox),
         initialize: emptyFunction
     };
     _fitContentCommand = {
         params: ["target"], title: "toggle clusters",
-        script: "this.target.useClusters = !this.target.useClusters;",
+        script: "self.target.useClusters = !self.target.useClusters;",
         immediate: undoBatch((source: Doc[]) => this.target.useClusters = !this.target.useClusters),
         initialize: emptyFunction
     };
+    _saveFilterCommand = {
+        params: ["target"], title: "save filter",
+        script: "self.target._docFilters = copyField(self['target-docFilters']);",
+        immediate: undoBatch((source: Doc[]) => this.target._docFilters = undefined),
+        initialize: (button: Doc) => { button['target-docFilters'] = this.target._docFilters instanceof ObjectField && ObjectField.MakeCopy(this.target._docFilters as any as ObjectField); },
+    };
 
-    _freeform_commands = [this._viewCommand, this._fitContentCommand, this._clusterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand];
+    _freeform_commands = [this._viewCommand, this._saveFilterCommand, this._fitContentCommand, this._clusterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand];
     _stacking_commands = [this._contentCommand, this._templateCommand];
     _masonry_commands = [this._contentCommand, this._templateCommand];
     _schema_commands = [this._templateCommand, this._narrativeCommand];
-- 
cgit v1.2.3-70-g09d2


From 5fb6e6348b73c81c4f7900f819fc55fcffe2f661 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 26 Jul 2020 10:15:59 -0400
Subject: fixed copyField() to copy non-ObjectFields.  fixed docFilters button
 to work with no filter

---
 src/client/views/collections/CollectionMenu.tsx | 2 +-
 src/fields/Doc.ts                               | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 81c349b26..24be69050 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -111,7 +111,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
         params: ["target"], title: "save filter",
         script: "self.target._docFilters = copyField(self['target-docFilters']);",
         immediate: undoBatch((source: Doc[]) => this.target._docFilters = undefined),
-        initialize: (button: Doc) => { button['target-docFilters'] = this.target._docFilters instanceof ObjectField && ObjectField.MakeCopy(this.target._docFilters as any as ObjectField); },
+        initialize: (button: Doc) => { button['target-docFilters'] = this.target._docFilters instanceof ObjectField ? ObjectField.MakeCopy(this.target._docFilters as any as ObjectField) : ""; },
     };
 
     _freeform_commands = [this._viewCommand, this._saveFilterCommand, this._fitContentCommand, this._clusterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand];
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 3ea53a9e0..87acb2ea7 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1235,7 +1235,7 @@ Scripting.addGlobal(function getProto(doc: any) { return Doc.GetProto(doc); });
 Scripting.addGlobal(function getDocTemplate(doc?: any) { return Doc.getDocTemplate(doc); });
 Scripting.addGlobal(function getAlias(doc: any) { return Doc.MakeAlias(doc); });
 Scripting.addGlobal(function getCopy(doc: any, copyProto: any) { return doc.isTemplateDoc ? Doc.ApplyTemplate(doc) : Doc.MakeCopy(doc, copyProto); });
-Scripting.addGlobal(function copyField(field: any) { return ObjectField.MakeCopy(field); });
+Scripting.addGlobal(function copyField(field: any) { return field instanceof ObjectField ? ObjectField.MakeCopy(field) : field; });
 Scripting.addGlobal(function aliasDocs(field: any) { return Doc.aliasDocs(field); });
 Scripting.addGlobal(function docList(field: any) { return DocListCast(field); });
 Scripting.addGlobal(function setInPlace(doc: any, field: any, value: any) { return Doc.SetInPlace(doc, field, value, false); });
-- 
cgit v1.2.3-70-g09d2


From f869c7a75eb6a2f6e6301aa76c57e383b41d3fea Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Mon, 27 Jul 2020 11:52:37 -0400
Subject: added hypothesis icon to toolbar. fixed toolbar to update to any
 document selection with specific items for each type.

---
 package-lock.json                                  |  15 ++
 package.json                                       |   1 +
 src/client/views/MainView.tsx                      |   5 +-
 src/client/views/collections/CollectionMenu.tsx    | 221 ++++++++++++---------
 src/client/views/collections/CollectionSubView.tsx |   4 +-
 src/client/views/collections/CollectionView.tsx    |   2 +-
 src/client/views/nodes/DocumentView.tsx            |   1 +
 7 files changed, 149 insertions(+), 100 deletions(-)

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

diff --git a/package-lock.json b/package-lock.json
index 698bd60cc..51105842a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -301,6 +301,21 @@
                 "@fortawesome/fontawesome-common-types": "^0.2.29"
             }
         },
+        "@fortawesome/free-brands-svg-icons": {
+            "version": "5.14.0",
+            "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.14.0.tgz",
+            "integrity": "sha512-WsqPFTvJFI7MYkcy0jeFE2zY+blC4OrnB9MJOcn1NxRXT/sSfEEhrI7CwzIkiYajLiVDBKWeErYOvpsMeodmCQ==",
+            "requires": {
+                "@fortawesome/fontawesome-common-types": "^0.2.30"
+            },
+            "dependencies": {
+                "@fortawesome/fontawesome-common-types": {
+                    "version": "0.2.30",
+                    "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.30.tgz",
+                    "integrity": "sha512-TsRwpTuKwFNiPhk1UfKgw7zNPeV5RhNp2Uw3pws+9gDAkPGKrtjR1y2lI3SYn7+YzyfuNknflpBA1LRKjt7hMg=="
+                }
+            }
+        },
         "@fortawesome/free-regular-svg-icons": {
             "version": "5.13.1",
             "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.13.1.tgz",
diff --git a/package.json b/package.json
index 6c466825e..3b7b5f391 100644
--- a/package.json
+++ b/package.json
@@ -117,6 +117,7 @@
     },
     "dependencies": {
         "@fortawesome/fontawesome-svg-core": "^1.2.29",
+        "@fortawesome/free-brands-svg-icons": "^5.14.0",
         "@fortawesome/free-regular-svg-icons": "^5.13.1",
         "@fortawesome/free-solid-svg-icons": "^5.13.1",
         "@fortawesome/react-fontawesome": "^0.1.11",
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index ae3f05fb7..9fad612ee 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -1,5 +1,8 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
 
+import {
+    faHireAHelper
+} from '@fortawesome/free-brands-svg-icons';
 import {
     faTasks, faEdit, faTrashAlt, faPalette, faAngleRight, faBell, faTrash, faCamera, faExpand, faCaretDown, faCaretLeft, faCaretRight, faCaretSquareDown, faCaretSquareRight, faArrowsAltH, faPlus, faMinus,
     faTerminal, faToggleOn, faFile as fileSolid, faExternalLinkAlt, faLocationArrow, faSearch, faFileDownload, faStop, faCalculator, faWindowMaximize, faAddressCard,
@@ -150,7 +153,7 @@ export class MainView extends React.Component {
             faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTrashAlt, faAngleRight, faBell,
             faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight,
             faHeading, faRulerCombined, faFillDrip, faLink, faUnlink, faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSuperscript, faSubscript, faIndent, faEyeDropper,
-            faPaintRoller, faBars, faBrush, faShapes, faEllipsisH, faHandPaper, faMap, faUser);
+            faPaintRoller, faBars, faBrush, faShapes, faEllipsisH, faHandPaper, faMap, faUser, faHireAHelper);
         this.initEventListeners();
         this.initAuthenticationRouters();
     }
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 24be69050..0b30b5a5f 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -30,16 +30,28 @@ import { ObjectField } from "../../../fields/ObjectField";
 export default class CollectionMenu extends AntimodeMenu {
     static Instance: CollectionMenu;
 
-    @observable SelectedCollection: CollectionView | undefined;
+    @observable SelectedCollection: DocumentView | undefined;
+    @observable FieldKey: string;
 
     constructor(props: Readonly<{}>) {
         super(props);
+        this.FieldKey = "";
         CollectionMenu.Instance = this;
         this._canFade = false; // don't let the inking menu fade away
         this.Pinned = Cast(Doc.UserDoc()["menuCollections-pinned"], "boolean", true);
         this.jumpTo(300, 300);
     }
 
+    componentDidMount() {
+        reaction(() => SelectionManager.SelectedDocuments().length && SelectionManager.SelectedDocuments()[0],
+            (doc) => doc && this.SetSelection(doc))
+    }
+
+    @action
+    SetSelection(view: DocumentView) {
+        this.SelectedCollection = view;
+    }
+
     @action
     toggleMenuPin = (e: React.MouseEvent) => {
         Doc.UserDoc()["menuCollections-pinned"] = this.Pinned = !this.Pinned;
@@ -54,14 +66,18 @@ export default class CollectionMenu extends AntimodeMenu {
         </button>;
 
         return this.getElement(!this.SelectedCollection ? [button] :
-            [<CollectionViewBaseChrome key="chrome" CollectionView={this.SelectedCollection} type={StrCast(this.SelectedCollection.props.Document._viewType) as CollectionViewType} />,
+            [<CollectionViewBaseChrome key="chrome"
+                docView={this.SelectedCollection}
+                fieldKey={Doc.LayoutFieldKey(this.SelectedCollection?.props.Document)}
+                type={StrCast(this.SelectedCollection?.props.Document._viewType, CollectionViewType.Invalid) as CollectionViewType} />,
                 button]);
     }
 }
 
 interface CollectionMenuProps {
-    CollectionView: CollectionView;
     type: CollectionViewType;
+    fieldKey: string;
+    docView: DocumentView;
 }
 
 const stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation();
@@ -70,7 +86,8 @@ const stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation();
 export class CollectionViewBaseChrome extends React.Component<CollectionMenuProps> {
     //(!)?\(\(\(doc.(\w+) && \(doc.\w+ as \w+\).includes\(\"(\w+)\"\)
 
-    get target() { return this.props.CollectionView.props.Document; }
+    get document() { return this.props.docView?.props.Document; }
+    get target() { return this.document; }
     _templateCommand = {
         params: ["target", "source"], title: "item view",
         script: "self.target.childLayoutTemplate = getDocTemplate(self.source?.[0])",
@@ -121,16 +138,16 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
     _tree_commands = [];
     private get _buttonizableCommands() {
         switch (this.props.type) {
+            default:
+            case CollectionViewType.Freeform: return this._freeform_commands;
             case CollectionViewType.Tree: return this._tree_commands;
             case CollectionViewType.Schema: return this._schema_commands;
             case CollectionViewType.Stacking: return this._stacking_commands;
             case CollectionViewType.Masonry: return this._stacking_commands;
-            case CollectionViewType.Freeform: return this._freeform_commands;
             case CollectionViewType.Time: return this._freeform_commands;
             case CollectionViewType.Carousel: return this._freeform_commands;
             case CollectionViewType.Carousel3D: return this._freeform_commands;
         }
-        return [];
     }
     private _picker: any;
     private _commandRef = React.createRef<HTMLInputElement>();
@@ -165,21 +182,16 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
 
     @computed get subChrome() {
         switch (this.props.type) {
-            case CollectionViewType.Freeform: return (<CollectionFreeFormViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
-            case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
-            case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
-            case CollectionViewType.Tree: return (<CollectionTreeViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
-            case CollectionViewType.Masonry: return (<CollectionStackingViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
-            case CollectionViewType.Carousel3D: return (<Collection3DCarouselViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
-            case CollectionViewType.Grid: return (<CollectionGridViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
-            default: return null;
+            default:
+            case CollectionViewType.Freeform: return (<CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={this.props.type === CollectionViewType.Invalid} />);
+            case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" {...this.props} />);
+            case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" {...this.props} />);
+            case CollectionViewType.Tree: return (<CollectionTreeViewChrome key="collchrome" {...this.props} />);
+            case CollectionViewType.Masonry: return (<CollectionStackingViewChrome key="collchrome" {...this.props} />);
+            case CollectionViewType.Carousel3D: return (<Collection3DCarouselViewChrome key="collchrome" {...this.props} />);
+            case CollectionViewType.Grid: return (<CollectionGridViewChrome key="collchrome" {...this.props} />);
         }
     }
-
-    private get document() {
-        return this.props.CollectionView.props.Document;
-    }
-
     private dropDisposer?: DragManager.DragDropDisposer;
     protected createDropTarget = (ele: HTMLDivElement) => {
         this.dropDisposer?.();
@@ -201,15 +213,15 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
 
     dragViewDown = (e: React.PointerEvent) => {
         setupMoveUpEvents(this, e, (e, down, delta) => {
-            const vtype = this.props.CollectionView.collectionViewType;
+            const vtype = this.props.type;
             const c = {
                 params: ["target"], title: vtype,
-                script: `this.target._viewType = '${StrCast(this.props.CollectionView.props.Document._viewType)}'`,
-                immediate: (source: Doc[]) => this.props.CollectionView.props.Document._viewType = Doc.getDocTemplate(source?.[0]),
+                script: `this.target._viewType = '${StrCast(this.props.type)}'`,
+                immediate: (source: Doc[]) => this.document._viewType = Doc.getDocTemplate(source?.[0]),
                 initialize: emptyFunction,
             };
             DragManager.StartButtonDrag([this._viewRef.current!], c.script, StrCast(c.title),
-                { target: this.props.CollectionView.props.Document }, c.params, c.initialize, e.clientX, e.clientY);
+                { target: this.document }, c.params, c.initialize, e.clientX, e.clientY);
             return true;
         }, emptyFunction, emptyFunction);
     }
@@ -217,7 +229,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
         setupMoveUpEvents(this, e, (e, down, delta) => {
             this._buttonizableCommands.filter(c => c.title === this._currentKey).map(c =>
                 DragManager.StartButtonDrag([this._commandRef.current!], c.script, c.title,
-                    { target: this.props.CollectionView.props.Document }, c.params, c.initialize, e.clientX, e.clientY));
+                    { target: this.document }, c.params, c.initialize, e.clientX, e.clientY));
             return true;
         }, emptyFunction, () => {
             this._buttonizableCommands.filter(c => c.title === this._currentKey).map(c => c.immediate([]));
@@ -251,7 +263,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
                     className="collectionViewBaseChrome-viewPicker"
                     onPointerDown={stopPropagation}
                     onChange={this.viewChanged}
-                    value={StrCast(this.props.CollectionView.props.Document._viewType)}>
+                    value={StrCast(this.props.type)}>
                     {Object.values(CollectionViewType).map(type => [CollectionViewType.Invalid, CollectionViewType.Docking].includes(type) ? (null) : (
                         <option
                             key={Utils.GenerateGuid()}
@@ -271,7 +283,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
             <div className="collectionMenu-cont" >
                 <div className="collectionMenu">
                     <div className="collectionViewBaseChrome">
-                        {this.viewModes}
+                        {this.props.type === CollectionViewType.Invalid ? (null) : this.viewModes}
                         {this.templateChrome}
                         <div className="collectionViewBaseChrome-viewSpecs" title="filter documents to show" style={{ display: "grid" }}>
                             <button className={"antimodeMenu-button"} onClick={this.toggleViewSpecs} >
@@ -287,15 +299,15 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
 }
 
 @observer
-export class CollectionFreeFormViewChrome extends React.Component<CollectionMenuProps> {
+export class CollectionFreeFormViewChrome extends React.Component<CollectionMenuProps & { isOverlay: boolean }> {
     public static Instance: CollectionFreeFormViewChrome;
     constructor(props: any) {
         super(props);
         CollectionFreeFormViewChrome.Instance = this;
     }
-    get Document() { return this.props.CollectionView.props.Document; }
+    get document() { return this.props.docView.props.Document; }
     @computed get dataField() {
-        return this.props.CollectionView.props.Document[Doc.LayoutFieldKey(this.props.CollectionView.props.Document)];
+        return this.document[Doc.LayoutFieldKey(this.document)];
     }
     @computed get childDocs() {
         return DocListCast(this.dataField);
@@ -303,30 +315,30 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     @undoBatch
     @action
     nextKeyframe = (): void => {
-        const currentFrame = Cast(this.Document.currentFrame, "number", null);
+        const currentFrame = Cast(this.document.currentFrame, "number", null);
         if (currentFrame === undefined) {
-            this.Document.currentFrame = 0;
+            this.document.currentFrame = 0;
             CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0);
         }
         CollectionFreeFormDocumentView.updateKeyframe(this.childDocs, currentFrame || 0);
-        this.Document.currentFrame = Math.max(0, (currentFrame || 0) + 1);
-        this.Document.lastFrame = Math.max(NumCast(this.Document.currentFrame), NumCast(this.Document.lastFrame));
+        this.document.currentFrame = Math.max(0, (currentFrame || 0) + 1);
+        this.document.lastFrame = Math.max(NumCast(this.document.currentFrame), NumCast(this.document.lastFrame));
     }
     @undoBatch
     @action
     prevKeyframe = (): void => {
-        const currentFrame = Cast(this.Document.currentFrame, "number", null);
+        const currentFrame = Cast(this.document.currentFrame, "number", null);
         if (currentFrame === undefined) {
-            this.Document.currentFrame = 0;
+            this.document.currentFrame = 0;
             CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0);
         }
         CollectionFreeFormDocumentView.gotoKeyframe(this.childDocs.slice());
-        this.Document.currentFrame = Math.max(0, (currentFrame || 0) - 1);
+        this.document.currentFrame = Math.max(0, (currentFrame || 0) - 1);
     }
     @undoBatch
     @action
     miniMap = (): void => {
-        this.Document.hideMinimap = !this.Document.hideMinimap;
+        this.document.hideMinimap = !this.document.hideMinimap;
     }
     private _palette = ["#D0021B", "#F5A623", "#F8E71C", "#8B572A", "#7ED321", "#417505", "#9013FE", "#4A90E2", "#50E3C2", "#B8E986", "#000000", "#4A4A4A", "#9B9B9B", "#FFFFFF", ""];
     private _width = ["1", "5", "10", "100"];
@@ -467,28 +479,39 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     }
 
     render() {
-        return this.Document.isAnnotationOverlay ? (null) :
-            <div className="collectionFreeFormMenu-cont">
+        return <div className="collectionFreeFormMenu-cont">
+            {this.props.docView.props.renderDepth !== 0 ? (null) :
                 <div key="map" title="mini map" className="backKeyframe" onClick={this.miniMap}>
                     <FontAwesomeIcon icon={"map"} size={"lg"} />
                 </div>
-                <div key="back" title="back frame" className="backKeyframe" onClick={this.prevKeyframe}>
-                    <FontAwesomeIcon icon={"caret-left"} size={"lg"} />
-                </div>
-                <div key="num" title="toggle view all" className="numKeyframe" style={{ backgroundColor: this.Document.editing ? "#759c75" : "#c56565" }}
-                    onClick={action(() => this.Document.editing = !this.Document.editing)} >
-                    {NumCast(this.Document.currentFrame)}
-                </div>
-                <div key="fwd" title="forward frame" className="fwdKeyframe" onClick={this.nextKeyframe}>
-                    <FontAwesomeIcon icon={"caret-right"} size={"lg"} />
-                </div>
+            }
+            <div key="back" title="back frame" className="backKeyframe" onClick={this.prevKeyframe}>
+                <FontAwesomeIcon icon={"caret-left"} size={"lg"} />
+            </div>
+            <div key="num" title="toggle view all" className="numKeyframe" style={{ backgroundColor: this.document.editing ? "#759c75" : "#c56565" }}
+                onClick={action(() => this.document.editing = !this.document.editing)} >
+                {NumCast(this.document.currentFrame)}
+            </div>
+            <div key="fwd" title="forward frame" className="fwdKeyframe" onClick={this.nextKeyframe}>
+                <FontAwesomeIcon icon={"caret-right"} size={"lg"} />
+            </div>
 
-                {this.widthPicker}
-                {this.colorPicker}
-                {this.fillPicker}
-                {this.drawButtons}
-                {this.formatPane}
-            </div>;
+            {!this.props.isOverlay ? (null) :
+                <button className={"antimodeMenu-button"} key="hypothesis" style={{ backgroundColor: !this.props.docView.layoutDoc.isAnnotating ? "121212" : undefined }} title="Use Hypothesis" onClick={() => this.props.docView.layoutDoc.isAnnotating = !this.props.docView.layoutDoc.isAnnotating}>
+                    <FontAwesomeIcon icon={["fab", "hire-a-helper"]} size={"lg"} />
+                </button>
+            }
+            {!this.props.isOverlay || this.props.docView.layoutDoc.isAnnotating ?
+                <>
+                    {this.widthPicker}
+                    {this.colorPicker}
+                    {this.fillPicker}
+                    {this.drawButtons}
+                    {this.formatPane}
+                </> :
+                (null)
+            }
+        </div>;
     }
 }
 @observer
@@ -496,12 +519,14 @@ export class CollectionStackingViewChrome extends React.Component<CollectionMenu
     @observable private _currentKey: string = "";
     @observable private suggestions: string[] = [];
 
-    @computed private get descending() { return StrCast(this.props.CollectionView.props.Document._columnsSort) === "descending"; }
-    @computed get pivotField() { return StrCast(this.props.CollectionView.props.Document._pivotField); }
+    get document() { return this.props.docView.props.Document; }
+
+    @computed private get descending() { return StrCast(this.document._columnsSort) === "descending"; }
+    @computed get pivotField() { return StrCast(this.document._pivotField); }
 
     getKeySuggestions = async (value: string): Promise<string[]> => {
         value = value.toLowerCase();
-        const docs = DocListCast(this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey]);
+        const docs = DocListCast(this.document[this.props.fieldKey]);
         if (docs instanceof Doc) {
             return Object.keys(docs).filter(key => key.toLowerCase().startsWith(value));
         } else {
@@ -536,14 +561,14 @@ export class CollectionStackingViewChrome extends React.Component<CollectionMenu
 
     @action
     setValue = (value: string) => {
-        this.props.CollectionView.props.Document._pivotField = value;
+        this.document._pivotField = value;
         return true;
     }
 
     @action toggleSort = () => {
-        this.props.CollectionView.props.Document._columnsSort =
-            this.props.CollectionView.props.Document._columnsSort === "descending" ? "ascending" :
-                this.props.CollectionView.props.Document._columnsSort === "ascending" ? undefined : "descending";
+        this.document._columnsSort =
+            this.document._columnsSort === "descending" ? "ascending" :
+                this.document._columnsSort === "ascending" ? undefined : "descending";
     }
     @action resetValue = () => { this._currentKey = this.pivotField; };
 
@@ -593,35 +618,36 @@ export class CollectionStackingViewChrome extends React.Component<CollectionMenu
 
 @observer
 export class CollectionSchemaViewChrome extends React.Component<CollectionMenuProps> {
-    // private _textwrapAllRows: boolean = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
+    // private _textwrapAllRows: boolean = Cast(this.document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
+    get document() { return this.props.docView.props.Document; }
 
     @undoBatch
     togglePreview = () => {
         const dividerWidth = 4;
         const borderWidth = Number(COLLECTION_BORDER_WIDTH);
-        const panelWidth = this.props.CollectionView.props.PanelWidth();
-        const previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth);
+        const panelWidth = this.props.docView.props.PanelWidth();
+        const previewWidth = NumCast(this.document.schemaPreviewWidth);
         const tableWidth = panelWidth - 2 * borderWidth - dividerWidth - previewWidth;
-        this.props.CollectionView.props.Document.schemaPreviewWidth = previewWidth === 0 ? Math.min(tableWidth / 3, 200) : 0;
+        this.document.schemaPreviewWidth = previewWidth === 0 ? Math.min(tableWidth / 3, 200) : 0;
     }
 
     @undoBatch
     @action
     toggleTextwrap = async () => {
-        const textwrappedRows = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []);
+        const textwrappedRows = Cast(this.document.textwrappedSchemaRows, listSpec("string"), []);
         if (textwrappedRows.length) {
-            this.props.CollectionView.props.Document.textwrappedSchemaRows = new List<string>([]);
+            this.document.textwrappedSchemaRows = new List<string>([]);
         } else {
-            const docs = DocListCast(this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey]);
+            const docs = DocListCast(this.document[this.props.fieldKey]);
             const allRows = docs instanceof Doc ? [docs[Id]] : docs.map(doc => doc[Id]);
-            this.props.CollectionView.props.Document.textwrappedSchemaRows = new List<string>(allRows);
+            this.document.textwrappedSchemaRows = new List<string>(allRows);
         }
     }
 
 
     render() {
-        const previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth);
-        const textWrapped = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
+        const previewWidth = NumCast(this.document.schemaPreviewWidth);
+        const textWrapped = Cast(this.document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
 
         return (
             <div className="collectionSchemaViewChrome-cont">
@@ -641,11 +667,12 @@ export class CollectionSchemaViewChrome extends React.Component<CollectionMenuPr
 @observer
 export class CollectionTreeViewChrome extends React.Component<CollectionMenuProps> {
 
+    get document() { return this.props.docView.props.Document; }
     get sortAscending() {
-        return this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey + "-sortAscending"];
+        return this.document[this.props.fieldKey + "-sortAscending"];
     }
     set sortAscending(value) {
-        this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey + "-sortAscending"] = value;
+        this.document[this.props.fieldKey + "-sortAscending"] = value;
     }
     @computed private get ascending() {
         return Cast(this.sortAscending, "boolean", null);
@@ -676,15 +703,16 @@ export class CollectionTreeViewChrome extends React.Component<CollectionMenuProp
 // Enter scroll speed for 3D Carousel 
 @observer
 export class Collection3DCarouselViewChrome extends React.Component<CollectionMenuProps> {
+    get document() { return this.props.docView.props.Document; }
     @computed get scrollSpeed() {
-        return this.props.CollectionView.props.Document._autoScrollSpeed;
+        return this.document._autoScrollSpeed;
     }
 
     @action
     setValue = (value: string) => {
         const numValue = Number(StrCast(value));
         if (numValue > 0) {
-            this.props.CollectionView.props.Document._autoScrollSpeed = numValue;
+            this.document._autoScrollSpeed = numValue;
             return true;
         }
         return false;
@@ -721,13 +749,14 @@ export class CollectionGridViewChrome extends React.Component<CollectionMenuProp
     private decrementLimitReached: boolean = false;
     @observable private resize = false;
     private resizeListenerDisposer: Opt<Lambda>;
+    get document() { return this.props.docView.props.Document; }
 
     componentDidMount() {
 
-        runInAction(() => this.resize = this.props.CollectionView.props.PanelWidth() < 700);
+        runInAction(() => this.resize = this.props.docView.props.PanelWidth() < 700);
 
         // listener to reduce text on chrome resize (panel resize)
-        this.resizeListenerDisposer = computed(() => this.props.CollectionView.props.PanelWidth()).observe(({ newValue }) => {
+        this.resizeListenerDisposer = computed(() => this.props.docView.props.PanelWidth()).observe(({ newValue }) => {
             runInAction(() => this.resize = newValue < 700);
         });
     }
@@ -736,7 +765,7 @@ export class CollectionGridViewChrome extends React.Component<CollectionMenuProp
         this.resizeListenerDisposer?.();
     }
 
-    get numCols() { return NumCast(this.props.CollectionView.props.Document.gridNumCols, 10); }
+    get numCols() { return NumCast(this.document.gridNumCols, 10); }
 
     /**
      * Sets the value of `numCols` on the grid's Document to the value entered.
@@ -745,7 +774,7 @@ export class CollectionGridViewChrome extends React.Component<CollectionMenuProp
     onNumColsEnter = (e: React.KeyboardEvent<HTMLInputElement>) => {
         if (e.key === "Enter" || e.key === "Tab") {
             if (e.currentTarget.valueAsNumber > 0) {
-                this.props.CollectionView.props.Document.gridNumCols = e.currentTarget.valueAsNumber;
+                this.document.gridNumCols = e.currentTarget.valueAsNumber;
             }
 
         }
@@ -757,8 +786,8 @@ export class CollectionGridViewChrome extends React.Component<CollectionMenuProp
     // @undoBatch
     // onRowHeightEnter = (e: React.KeyboardEvent<HTMLInputElement>) => {
     //     if (e.key === "Enter" || e.key === "Tab") {
-    //         if (e.currentTarget.valueAsNumber > 0 && this.props.CollectionView.props.Document.rowHeight as number !== e.currentTarget.valueAsNumber) {
-    //             this.props.CollectionView.props.Document.rowHeight = e.currentTarget.valueAsNumber;
+    //         if (e.currentTarget.valueAsNumber > 0 && this.document.rowHeight as number !== e.currentTarget.valueAsNumber) {
+    //             this.document.rowHeight = e.currentTarget.valueAsNumber;
     //         }
     //     }
     // }
@@ -768,7 +797,7 @@ export class CollectionGridViewChrome extends React.Component<CollectionMenuProp
      */
     @undoBatch
     toggleFlex = () => {
-        this.props.CollectionView.props.Document.gridFlex = !BoolCast(this.props.CollectionView.props.Document.gridFlex, true);
+        this.document.gridFlex = !BoolCast(this.document.gridFlex, true);
     }
 
     /**
@@ -776,8 +805,8 @@ export class CollectionGridViewChrome extends React.Component<CollectionMenuProp
      */
     onIncrementButtonClick = () => {
         this.clicked = true;
-        this.entered && (this.props.CollectionView.props.Document.gridNumCols as number)--;
-        undoBatch(() => this.props.CollectionView.props.Document.gridNumCols = this.numCols + 1)();
+        this.entered && (this.document.gridNumCols as number)--;
+        undoBatch(() => this.document.gridNumCols = this.numCols + 1)();
         this.entered = false;
     }
 
@@ -787,8 +816,8 @@ export class CollectionGridViewChrome extends React.Component<CollectionMenuProp
     onDecrementButtonClick = () => {
         this.clicked = true;
         if (!this.decrementLimitReached) {
-            this.entered && (this.props.CollectionView.props.Document.gridNumCols as number)++;
-            undoBatch(() => this.props.CollectionView.props.Document.gridNumCols = this.numCols - 1)();
+            this.entered && (this.document.gridNumCols as number)++;
+            undoBatch(() => this.document.gridNumCols = this.numCols - 1)();
         }
         this.entered = false;
     }
@@ -799,7 +828,7 @@ export class CollectionGridViewChrome extends React.Component<CollectionMenuProp
     incrementValue = () => {
         this.entered = true;
         if (!this.clicked && !this.decrementLimitReached) {
-            this.props.CollectionView.props.Document.gridNumCols = this.numCols + 1;
+            this.document.gridNumCols = this.numCols + 1;
         }
         this.decrementLimitReached = false;
         this.clicked = false;
@@ -812,7 +841,7 @@ export class CollectionGridViewChrome extends React.Component<CollectionMenuProp
         this.entered = true;
         if (!this.clicked) {
             if (this.numCols !== 1) {
-                this.props.CollectionView.props.Document.gridNumCols = this.numCols - 1;
+                this.document.gridNumCols = this.numCols - 1;
             }
             else {
                 this.decrementLimitReached = true;
@@ -826,7 +855,7 @@ export class CollectionGridViewChrome extends React.Component<CollectionMenuProp
      * Toggles the value of preventCollision
      */
     toggleCollisions = () => {
-        this.props.CollectionView.props.Document.gridPreventCollision = !this.props.CollectionView.props.Document.gridPreventCollision;
+        this.document.gridPreventCollision = !this.document.gridPreventCollision;
     }
 
     /**
@@ -834,7 +863,7 @@ export class CollectionGridViewChrome extends React.Component<CollectionMenuProp
      */
     changeCompactType = (e: React.ChangeEvent<HTMLSelectElement>) => {
         // need to change startCompaction so that this operation will be undoable.
-        this.props.CollectionView.props.Document.gridStartCompaction = e.target.selectedOptions[0].value;
+        this.document.gridStartCompaction = e.target.selectedOptions[0].value;
     }
 
     render() {
@@ -852,10 +881,10 @@ export class CollectionGridViewChrome extends React.Component<CollectionMenuProp
                     <span className="grid-icon">
                         <FontAwesomeIcon icon="text-height" size="1x" />
                     </span>
-                    <input className="collectionGridViewChrome-entryBox" type="number" placeholder={this.props.CollectionView.props.Document.rowHeight as string} onKeyDown={this.onRowHeightEnter} onClick={(e: React.MouseEvent<HTMLInputElement, MouseEvent>) => { e.stopPropagation(); e.preventDefault(); e.currentTarget.focus(); }} />
+                    <input className="collectionGridViewChrome-entryBox" type="number" placeholder={this.document.rowHeight as string} onKeyDown={this.onRowHeightEnter} onClick={(e: React.MouseEvent<HTMLInputElement, MouseEvent>) => { e.stopPropagation(); e.preventDefault(); e.currentTarget.focus(); }} />
                 </span> */}
                 <span className="grid-control" style={{ width: this.resize ? "12%" : "20%" }}>
-                    <input type="checkbox" style={{ marginRight: 5 }} onChange={this.toggleCollisions} checked={!this.props.CollectionView.props.Document.gridPreventCollision} />
+                    <input type="checkbox" style={{ marginRight: 5 }} onChange={this.toggleCollisions} checked={!this.document.gridPreventCollision} />
                     <label className="flexLabel">{this.resize ? "Coll" : "Collisions"}</label>
                 </span>
 
@@ -863,7 +892,7 @@ export class CollectionGridViewChrome extends React.Component<CollectionMenuProp
                     style={{ marginRight: 5 }}
                     onPointerDown={stopPropagation}
                     onChange={this.changeCompactType}
-                    value={StrCast(this.props.CollectionView.props.Document.gridStartCompaction, StrCast(this.props.CollectionView.props.Document.gridCompaction))}>
+                    value={StrCast(this.document.gridStartCompaction, StrCast(this.document.gridCompaction))}>
                     {["vertical", "horizontal", "none"].map(type =>
                         <option className="collectionGridViewChrome-viewOption"
                             onPointerDown={stopPropagation}
@@ -875,11 +904,11 @@ export class CollectionGridViewChrome extends React.Component<CollectionMenuProp
 
                 <span className="grid-control" style={{ width: this.resize ? "12%" : "20%" }}>
                     <input style={{ marginRight: 5 }} type="checkbox" onChange={this.toggleFlex}
-                        checked={BoolCast(this.props.CollectionView.props.Document.gridFlex, true)} />
+                        checked={BoolCast(this.document.gridFlex, true)} />
                     <label className="flexLabel">{this.resize ? "Flex" : "Flexible"}</label>
                 </span>
 
-                <button onClick={() => this.props.CollectionView.props.Document.gridResetLayout = true}>
+                <button onClick={() => this.document.gridResetLayout = true}>
                     {!this.resize ? "Reset" :
                         <FontAwesomeIcon icon="redo-alt" size="1x" />}
                 </button>
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 8480a56cc..d9d9c0eb8 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -292,7 +292,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
                             const reg = new RegExp(Utils.prepend(""), "g");
                             const modHtml = srcUrl ? html.replace(reg, srcUrl) : html;
                             const htmlDoc = Docs.Create.HtmlDocument(modHtml, { ...options, title: "-web page-", _width: 300, _height: 300 });
-                            Doc.GetProto(htmlDoc)["data-text"] = text;
+                            Doc.GetProto(htmlDoc)["data-text"] = Doc.GetProto(htmlDoc)["text"] = text;
                             this.props.addDocument(htmlDoc);
                             if (srcWeb) {
                                 const focusNode = (SelectionManager.SelectedDocuments()[0].ContentDiv?.getElementsByTagName("iframe")[0].contentDocument?.getSelection()?.focusNode as any);
@@ -300,7 +300,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
                                     const rect = "getBoundingClientRect" in focusNode ? focusNode.getBoundingClientRect() : focusNode?.parentElement.getBoundingClientRect();
                                     const x = (rect?.x || 0);
                                     const y = NumCast(srcWeb._scrollTop) + (rect?.y || 0);
-                                    const anchor = Docs.Create.FreeformDocument([], { _backgroundColor: "transparent", _width: 25, _height: 25, x, y, annotationOn: srcWeb });
+                                    const anchor = Docs.Create.FreeformDocument([], { _backgroundColor: "transparent", _width: 75, _height: 40, x, y, annotationOn: srcWeb });
                                     anchor.context = srcWeb;
                                     const key = Doc.LayoutFieldKey(srcWeb);
                                     Doc.AddDocToList(srcWeb, key + "-annotations", anchor);
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index a82c91383..2c17254ed 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -577,7 +577,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
             ChildLayoutTemplate: this.childLayoutTemplate,
             ChildLayoutString: this.childLayoutString,
         };
-        setTimeout(action(() => this.props.isSelected(true) && (CollectionMenu.Instance.SelectedCollection = this)), 0);
+        setTimeout(() => this.props.isSelected(true) && CollectionMenu.Instance.SetSelection(this, this.props.fieldKey), 0);
         const boxShadow = Doc.UserDoc().renderStyle === "comic" || this.props.Document.isBackground || this.collectionViewType === CollectionViewType.Linear ? undefined :
             `${Cast(Doc.UserDoc().activeWorkspace, Doc, null)?.darkScheme ? "rgb(30, 32, 31) " : "#9c9396 "} ${StrCast(this.props.Document.boxShadow, "0.2vw 0.2vw 0.8vw")}`;
         return (<div className={"collectionView"} onContextMenu={this.onContextMenu}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index b59875a7e..7f86ec98e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -44,6 +44,7 @@ import { MobileInterface } from '../../../mobile/MobileInterface';
 import { TaskCompletionBox } from './TaskCompletedBox';
 import { LinkDescriptionPopup } from './LinkDescriptionPopup';
 import { LinkManager } from '../../util/LinkManager';
+import CollectionMenu from '../collections/CollectionMenu';
 
 library.add(fa.faEdit, fa.faTrash, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faCompressArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faAlignCenter, fa.faCaretSquareRight,
     fa.faSquare, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faLink, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, fa.faLock, fa.faLaptopCode, fa.faMale,
-- 
cgit v1.2.3-70-g09d2


From f90129fb34c23d902273873a7681755ddc8464f3 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 28 Jul 2020 08:38:53 -0400
Subject: fixed crashes in collectionMenu when a collectoins ACLs make it
 unreadable

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

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

diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 0b30b5a5f..5aa535d26 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -479,7 +479,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     }
 
     render() {
-        return <div className="collectionFreeFormMenu-cont">
+        return !this.props.docView.layoutDoc ? (null) : <div className="collectionFreeFormMenu-cont">
             {this.props.docView.props.renderDepth !== 0 ? (null) :
                 <div key="map" title="mini map" className="backKeyframe" onClick={this.miniMap}>
                     <FontAwesomeIcon icon={"map"} size={"lg"} />
-- 
cgit v1.2.3-70-g09d2


From 14bc3337ce2c2ca87f4b11765414a7ee1bb12bba Mon Sep 17 00:00:00 2001
From: yunahi <60233430+yunahi@users.noreply.github.com>
Date: Wed, 29 Jul 2020 00:14:37 +0900
Subject: test

---
 src/client/views/collections/CollectionMenu.tsx | 35 ++++++++++++++++---------
 1 file changed, 22 insertions(+), 13 deletions(-)

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

diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 0b30b5a5f..4fa2e51e8 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -25,6 +25,7 @@ import { SelectionManager } from "../../util/SelectionManager";
 import { DocumentView } from "../nodes/DocumentView";
 import { ColorState } from "react-color";
 import { ObjectField } from "../../../fields/ObjectField";
+import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
 
 @observer
 export default class CollectionMenu extends AntimodeMenu {
@@ -342,11 +343,17 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
     }
     private _palette = ["#D0021B", "#F5A623", "#F8E71C", "#8B572A", "#7ED321", "#417505", "#9013FE", "#4A90E2", "#50E3C2", "#B8E986", "#000000", "#4A4A4A", "#9B9B9B", "#FFFFFF", ""];
     private _width = ["1", "5", "10", "100"];
-    private _draw = ["⎯", "→", "↔︎", "∿", "↝", "↭", "ロ", "O", "∆"];
-    private _head = ["", "", "arrow", "", "", "arrow", "", "", ""];
-    private _end = ["", "arrow", "arrow", "", "arrow", "arrow", "", "", ""];
-    private _shape = ["line", "line", "line", "", "", "", "rectangle", "circle", "triangle"];
-
+    // private _draw = ["⎯", "→", "↔︎", "∿", "↝", "↭", "ロ", "O", "∆"];
+    // private _head = ["", "", "arrow", "", "", "arrow", "", "", ""];
+    // private _end = ["", "arrow", "arrow", "", "arrow", "arrow", "", "", ""];
+    // private _shape = ["line", "line", "line", "", "", "", "rectangle", "circle", "triangle"];
+    private _dotsize = [10, 20, 30, 40];
+    private _draw = ["∿", "⎯", "→", "↔︎", "ロ", "O"];
+    private _head = ["", "", "", "arrow", "", ""];
+    private _end = ["", "", "arrow", "arrow", "", ""];
+    private _shape = ["", "line", "line", "line", "rectangle", "circle"];
+    private _title = ["pen", "line", "line with arrow", "line with double arrows", "square", "circle",];
+    private _faName = ["pen-fancy", "minus", "long-arrow-alt-right", "arrows-alt-h", "square", "circle"];
     @observable _shapesNum = this._shape.length;
     @observable _selected = this._shapesNum;
 
@@ -409,9 +416,11 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
         });
         return <div className="btn-draw" key="draw">
             {this._draw.map((icon, i) =>
-                <button className="antimodeMenu-button" key={icon} onPointerDown={() => func(i, false)} onDoubleClick={() => func(i, true)}
+                <button className="antimodeMenu-button" title={this._title[i]} key={icon} onPointerDown={() => func(i, false)} onDoubleClick={() => func(i, true)}
                     style={{ backgroundColor: i === this._selected ? "121212" : "", fontSize: "20" }}>
-                    {this._draw[i]}
+                    {/* {this._draw[i]} */}
+                    <FontAwesomeIcon icon={this._faName[i] as IconProp} size="sm" />
+
                 </button>)}
         </div>;
     }
@@ -430,11 +439,11 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
         return !this._widthBtn ? widthPicker :
             <div className="btn2-group" key="width">
                 {widthPicker}
-                {this._width.map(wid =>
-                    <button className="antimodeMenu-button" key={wid}
+                {this._width.map((wid, i) =>
+                    <button className="antimodeMenu-button" key={wid} title="change width"
                         onPointerDown={action(() => { SetActiveInkWidth(wid); this._widthBtn = false; this.editProperties(wid, "width"); })}
-                        style={{ backgroundColor: this._widthBtn ? "121212" : "", zIndex: 1001 }}>
-                        {wid}
+                        style={{ backgroundColor: this._widthBtn ? "121212" : "", zIndex: 1001, fontSize: this._dotsize[i], padding: 0, textAlign: "center" }}>
+                        •
                     </button>)}
             </div>;
     }
@@ -474,7 +483,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
         return <button className="antimodeMenu-button" key="format" title="toggle foramatting pane"
             onPointerDown={action(e => FormatShapePane.Instance.Pinned = !FormatShapePane.Instance.Pinned)}
             style={{ backgroundColor: this._fillBtn ? "121212" : "" }}>
-            <FontAwesomeIcon icon="chevron-right" size="lg" />
+            <FontAwesomeIcon icon="angle-double-right" size="lg" />
         </button>;
     }
 
@@ -503,10 +512,10 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
             }
             {!this.props.isOverlay || this.props.docView.layoutDoc.isAnnotating ?
                 <>
+                    {this.drawButtons}
                     {this.widthPicker}
                     {this.colorPicker}
                     {this.fillPicker}
-                    {this.drawButtons}
                     {this.formatPane}
                 </> :
                 (null)
-- 
cgit v1.2.3-70-g09d2


From ef235dfa63709656af35fa3deaf53529abd3ee4c Mon Sep 17 00:00:00 2001
From: yunahi <60233430+yunahi@users.noreply.github.com>
Date: Wed, 29 Jul 2020 00:48:20 +0900
Subject:  moved inkmenu to collectionMenu

---
 src/client/views/DocumentDecorations.tsx        | 1 -
 src/client/views/collections/CollectionMenu.tsx | 2 ++
 2 files changed, 2 insertions(+), 1 deletion(-)

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

diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 3d258430e..c5e0a3303 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -526,7 +526,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
         SelectionManager.SelectedDocuments().forEach(action((element: DocumentView, index) => {
             const doc = Document(element.rootDoc);
             if (doc.type === DocumentType.INK && doc.x && doc.y && doc._height && doc._width) {
-                console.log(doc.x, doc.y, doc._height, doc._width);
                 const ink = Cast(doc.data, InkField)?.inkData;
                 if (ink) {
                     const newPoints: { X: number, Y: number }[] = [];
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 4fa2e51e8..f3b82df83 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -26,6 +26,8 @@ import { DocumentView } from "../nodes/DocumentView";
 import { ColorState } from "react-color";
 import { ObjectField } from "../../../fields/ObjectField";
 import { IconProp, library } from '@fortawesome/fontawesome-svg-core';
+import { faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSubscript, faSuperscript, faIndent, faEyeDropper, faCaretDown, faPalette, faArrowsAlt, faHighlighter, faLink, faPaintRoller, faSleigh, faBars, faFillDrip, faBrush, faPenNib, faShapes, faArrowLeft, faEllipsisH, faBezierCurve, faArrowRight, faArrowsAltH, faMinus, faCircle, faExclamationTriangle, faSquare, faLongArrowAltRight, faPenFancy, faCaretSquareRight, faAngleDoubleRight, } from "@fortawesome/free-solid-svg-icons";
+library.add(faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSuperscript, faSubscript, faIndent, faEyeDropper, faCaretDown, faPalette, faArrowsAlt, faHighlighter, faLink, faPaintRoller, faBars, faFillDrip, faBrush, faPenNib, faShapes, faArrowLeft, faEllipsisH, faBezierCurve, faLongArrowAltRight, faArrowsAltH, faMinus, faCircle, faSquare, faSquare, faPenFancy, faAngleDoubleRight,);
 
 @observer
 export default class CollectionMenu extends AntimodeMenu {
-- 
cgit v1.2.3-70-g09d2


From e3ead6afe43ce24caf58382bcb5fad294750dfa4 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Tue, 28 Jul 2020 19:07:38 -0400
Subject: added onClick draggable command for buttons

---
 src/client/views/collections/CollectionMenu.tsx | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 5aa535d26..47670eb26 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -101,11 +101,21 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
         initialize: emptyFunction,
     };
     _contentCommand = {
-        params: ["target", "source"], title: "clear content",
+        params: ["target", "source"], title: "set content",
         script: "getProto(self.target).data = copyField(self.source);",
         immediate: undoBatch((source: Doc[]) => Doc.GetProto(this.target).data = new List<Doc>(source)), // Doc.aliasDocs(source),
         initialize: emptyFunction,
     };
+    _onClickCommand = {
+        params: ["target", "proxy"], title: "copy onClick",
+        script: `{ if (self.proxy?.[0]) {
+             getProto(self.proxy[0]).onClick = copyField(self.target.onClick); 
+             getProto(self.proxy[0]).target = self.target.target;
+             getProto(self.proxy[0]).source = copyField(self.target.source); 
+            }}`,
+        immediate: undoBatch((source: Doc[]) => { }),
+        initialize: emptyFunction,
+    };
     _viewCommand = {
         params: ["target"], title: "bookmark view",
         script: "self.target._panX = self['target-panX']; self.target._panY = self['target-panY']; self.target._viewScale = self['target-viewScale'];",
@@ -135,10 +145,11 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
     _stacking_commands = [this._contentCommand, this._templateCommand];
     _masonry_commands = [this._contentCommand, this._templateCommand];
     _schema_commands = [this._templateCommand, this._narrativeCommand];
+    _doc_commands = [this._onClickCommand];
     _tree_commands = [];
     private get _buttonizableCommands() {
         switch (this.props.type) {
-            default:
+            default: return this._doc_commands;
             case CollectionViewType.Freeform: return this._freeform_commands;
             case CollectionViewType.Tree: return this._tree_commands;
             case CollectionViewType.Schema: return this._schema_commands;
-- 
cgit v1.2.3-70-g09d2


From 57c07152904762c790e3a3bb2003d389983990d8 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 29 Jul 2020 09:46:31 -0400
Subject: streamlined settin link follow tarets a bit by addin a follow link
 draggable UI button

---
 src/client/views/collections/CollectionMenu.tsx | 19 ++++++++++++++++++-
 src/fields/ScriptField.ts                       |  4 ++++
 2 files changed, 22 insertions(+), 1 deletion(-)

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

diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 47670eb26..3eda2e2f2 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -25,6 +25,7 @@ import { SelectionManager } from "../../util/SelectionManager";
 import { DocumentView } from "../nodes/DocumentView";
 import { ColorState } from "react-color";
 import { ObjectField } from "../../../fields/ObjectField";
+import { ScriptField } from "../../../fields/ScriptField";
 
 @observer
 export default class CollectionMenu extends AntimodeMenu {
@@ -116,6 +117,22 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
         immediate: undoBatch((source: Doc[]) => { }),
         initialize: emptyFunction,
     };
+    _openLinkInCommand = {
+        params: ["target", "container"], title: "link follow target",
+        script: `{ if (self.container?.length) {
+            getProto(self.target).linkContainer = self.container[0];
+            getProto(self.target).isLinkButton = true;
+            getProto(self.target).onClick = makeScript("getProto(self.linkContainer).data = new List([self.links[0]?.anchor2])");
+            }}`,
+        immediate: undoBatch((container: Doc[]) => {
+            if (container.length) {
+                Doc.GetProto(this.target).linkContainer = container[0];
+                Doc.GetProto(this.target).isLinkButton = true;
+                Doc.GetProto(this.target).onClick = ScriptField.MakeScript("getProto(self.linkContainer).data = new List([self.links[0]?.anchor2])");
+            }
+        }),
+        initialize: emptyFunction,
+    };
     _viewCommand = {
         params: ["target"], title: "bookmark view",
         script: "self.target._panX = self['target-panX']; self.target._panY = self['target-panY']; self.target._viewScale = self['target-viewScale'];",
@@ -145,7 +162,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
     _stacking_commands = [this._contentCommand, this._templateCommand];
     _masonry_commands = [this._contentCommand, this._templateCommand];
     _schema_commands = [this._templateCommand, this._narrativeCommand];
-    _doc_commands = [this._onClickCommand];
+    _doc_commands = [this._openLinkInCommand, this._onClickCommand];
     _tree_commands = [];
     private get _buttonizableCommands() {
         switch (this.props.type) {
diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts
index bd08b2f32..f55483a5b 100644
--- a/src/fields/ScriptField.ts
+++ b/src/fields/ScriptField.ts
@@ -183,6 +183,10 @@ Scripting.addGlobal(function getIndexVal(list: any[], index: number) {
     return list.reduce((p, x, i) => (i <= index && x !== undefined) || p === undefined ? x : p, undefined as any);
 }, "returns the value at a given index of a list", "(list: any[], index: number)");
 
+Scripting.addGlobal(function makeScript(script: string) {
+    return ScriptField.MakeScript(script);
+}, "returns the value at a given index of a list", "(list: any[], index: number)");
+
 export namespace ComputedField {
     let useComputed = true;
     export function DisableComputedFields() {
-- 
cgit v1.2.3-70-g09d2


From 0514d32ab83cc95e35e1fb855c3450f0c1984f9e Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 29 Jul 2020 14:18:53 -0400
Subject: fixed color box -- why was it commented out??  fixed workspace so
 that it can't be converted to another cllecction type

---
 src/client/views/collections/CollectionMenu.tsx | 13 ++++++--
 src/client/views/nodes/ColorBox.tsx             | 44 ++++++++++++-------------
 2 files changed, 31 insertions(+), 26 deletions(-)

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

diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index f9b944bb1..7b591e120 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -208,10 +208,10 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
         this.document._facetWidth = 0;
     }
 
-
     @computed get subChrome() {
         switch (this.props.type) {
             default:
+            case CollectionViewType.Docking: return (<CollectionDockingChrome key="collchrome" {...this.props} />);
             case CollectionViewType.Freeform: return (<CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={this.props.type === CollectionViewType.Invalid} />);
             case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" {...this.props} />);
             case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" {...this.props} />);
@@ -312,8 +312,8 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
             <div className="collectionMenu-cont" >
                 <div className="collectionMenu">
                     <div className="collectionViewBaseChrome">
-                        {this.props.type === CollectionViewType.Invalid ? (null) : this.viewModes}
-                        {this.templateChrome}
+                        {this.props.type === CollectionViewType.Invalid || this.props.type === CollectionViewType.Docking ? (null) : this.viewModes}
+                        {this.props.type === CollectionViewType.Invalid || this.props.type === CollectionViewType.Docking ? (null) : this.templateChrome}
                         <div className="collectionViewBaseChrome-viewSpecs" title="filter documents to show" style={{ display: "grid" }}>
                             <button className={"antimodeMenu-button"} onClick={this.toggleViewSpecs} >
                                 <FontAwesomeIcon icon="filter" size="lg" />
@@ -327,6 +327,13 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
     }
 }
 
+@observer
+export class CollectionDockingChrome extends React.Component<CollectionMenuProps> {
+    render() {
+        return (null);
+    }
+}
+
 @observer
 export class CollectionFreeFormViewChrome extends React.Component<CollectionMenuProps & { isOverlay: boolean }> {
     public static Instance: CollectionFreeFormViewChrome;
diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx
index b186d9ffc..090cf015a 100644
--- a/src/client/views/nodes/ColorBox.tsx
+++ b/src/client/views/nodes/ColorBox.tsx
@@ -54,30 +54,28 @@ export class ColorBox extends ViewBoxBaseComponent<FieldViewProps, ColorDocument
     }
     render() {
         const selDoc = SelectionManager.SelectedDocuments()?.[0]?.rootDoc;
-        // return <div className={`colorBox-container${this.active() ? "-interactive" : ""}`}
-        //     onPointerDown={e => e.button === 0 && !e.ctrlKey && e.stopPropagation()}
-        //     style={{ transform: `scale(${this.props.ContentScaling()})`, width: `${100 / this.props.ContentScaling()}%`, height: `${100 / this.props.ContentScaling()}%` }} >
+        return <div className={`colorBox-container${this.active() ? "-interactive" : ""}`}
+            onPointerDown={e => e.button === 0 && !e.ctrlKey && e.stopPropagation()}
+            style={{ transform: `scale(${this.props.ContentScaling()})`, width: `${100 / this.props.ContentScaling()}%`, height: `${100 / this.props.ContentScaling()}%` }} >
 
-        //     <SketchPicker onChange={ColorBox.switchColor} presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']}
-        //         color={StrCast(ActiveInkPen()?.backgroundColor,
-        //             StrCast(selDoc?._backgroundColor, StrCast(selDoc?.backgroundColor, "black")))} />
+            <SketchPicker onChange={ColorBox.switchColor} presetColors={['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent']}
+                color={StrCast(ActiveInkPen()?.backgroundColor,
+                    StrCast(selDoc?._backgroundColor, StrCast(selDoc?.backgroundColor, "black")))} />
 
-        //     <div style={{ display: "grid", gridTemplateColumns: "20% 80%", paddingTop: "10px" }}>
-        //         <div> {ActiveInkWidth() ?? 2}</div>
-        //         <input type="range" defaultValue={ActiveInkWidth() ?? 2} min={1} max={100} onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
-        //             SetActiveInkWidth(e.target.value);
-        //             SelectionManager.SelectedDocuments().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeWidth = Number(e.target.value));
-        //         }} />
-        //         <div> {ActiveInkBezierApprox() ?? 2}</div>
-        //         <input type="range" defaultValue={ActiveInkBezierApprox() ?? 2} min={0} max={300} onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
-        //             SetActiveBezierApprox(e.target.value);
-        //             SelectionManager.SelectedDocuments().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeBezier = e.target.value);
-        //         }} />
-        //         <br />
-        //         <br />
-        //     </div>
-        // </div>
-        //     ;
-        return <></>;
+            <div style={{ display: "grid", gridTemplateColumns: "20% 80%", paddingTop: "10px" }}>
+                <div> {ActiveInkWidth() ?? 2}</div>
+                <input type="range" defaultValue={ActiveInkWidth() ?? 2} min={1} max={100} onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
+                    SetActiveInkWidth(e.target.value);
+                    SelectionManager.SelectedDocuments().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeWidth = Number(e.target.value));
+                }} />
+                <div> {ActiveInkBezierApprox() ?? 2}</div>
+                <input type="range" defaultValue={ActiveInkBezierApprox() ?? 2} min={0} max={300} onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
+                    SetActiveBezierApprox(e.target.value);
+                    SelectionManager.SelectedDocuments().filter(i => StrCast(i.rootDoc.type) === DocumentType.INK).map(i => i.rootDoc.strokeBezier = e.target.value);
+                }} />
+                <br />
+                <br />
+            </div>
+        </div>;
     }
 }
-- 
cgit v1.2.3-70-g09d2


From d7a8e8fcf11c435c592381b8073c6fdf3e861974 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 29 Jul 2020 14:20:03 -0400
Subject: from last

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

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

diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 7b591e120..47c8addaa 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -211,7 +211,6 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
     @computed get subChrome() {
         switch (this.props.type) {
             default:
-            case CollectionViewType.Docking: return (<CollectionDockingChrome key="collchrome" {...this.props} />);
             case CollectionViewType.Freeform: return (<CollectionFreeFormViewChrome key="collchrome" {...this.props} isOverlay={this.props.type === CollectionViewType.Invalid} />);
             case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" {...this.props} />);
             case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" {...this.props} />);
@@ -219,6 +218,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
             case CollectionViewType.Masonry: return (<CollectionStackingViewChrome key="collchrome" {...this.props} />);
             case CollectionViewType.Carousel3D: return (<Collection3DCarouselViewChrome key="collchrome" {...this.props} />);
             case CollectionViewType.Grid: return (<CollectionGridViewChrome key="collchrome" {...this.props} />);
+            case CollectionViewType.Docking: return (<CollectionDockingChrome key="collchrome" {...this.props} />);
         }
     }
     private dropDisposer?: DragManager.DragDropDisposer;
-- 
cgit v1.2.3-70-g09d2


From 1a9a9f43210bb848fb511361b43903e07ea70722 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 29 Jul 2020 14:30:33 -0400
Subject: added divider line for web pae hypothesis switchin

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

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

diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 47c8addaa..d6cb79e9c 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -541,7 +541,10 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
             </div>
 
             {!this.props.isOverlay ? (null) :
-                <button className={"antimodeMenu-button"} key="hypothesis" style={{ backgroundColor: !this.props.docView.layoutDoc.isAnnotating ? "121212" : undefined }} title="Use Hypothesis" onClick={() => this.props.docView.layoutDoc.isAnnotating = !this.props.docView.layoutDoc.isAnnotating}>
+                <button className={"antimodeMenu-button"} key="hypothesis"
+                    style={{ backgroundColor: !this.props.docView.layoutDoc.isAnnotating ? "121212" : undefined, borderRight: "1px solid gray" }}
+                    title="Use Hypothesis"
+                    onClick={() => this.props.docView.layoutDoc.isAnnotating = !this.props.docView.layoutDoc.isAnnotating}>
                     <FontAwesomeIcon icon={["fab", "hire-a-helper"]} size={"lg"} />
                 </button>
             }
-- 
cgit v1.2.3-70-g09d2


From f3f51bb4933cada9ae83594912db10d88082be24 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 30 Jul 2020 10:53:21 -0400
Subject: made 'floatin' document API cleaner.  fixed interactions with draggin
 blue dots off and link lines to link documents.  removed Recommndations UI
 stuff.  changed treeView to avoid "No, no, no" error warnin when tryin to
 render promises

---
 src/client/documents/DocumentTypes.ts              |   1 -
 src/client/documents/Documents.ts                  |   9 -
 src/client/views/DocumentDecorations.tsx           |   2 +-
 src/client/views/GlobalKeyHandler.ts               |   1 -
 src/client/views/RecommendationsBox.scss           |  69 -------
 src/client/views/RecommendationsBox.tsx            | 201 ---------------------
 src/client/views/TemplateMenu.tsx                  |   6 +-
 src/client/views/collections/CollectionMenu.tsx    |   2 +-
 src/client/views/collections/CollectionSubView.tsx |   2 +-
 .../views/collections/CollectionTreeView.tsx       |   4 +-
 src/client/views/nodes/DocumentContentsView.tsx    |   3 +-
 src/client/views/nodes/DocumentView.tsx            |  33 ++--
 src/client/views/nodes/LinkAnchorBox.tsx           |   4 +-
 13 files changed, 30 insertions(+), 307 deletions(-)
 delete mode 100644 src/client/views/RecommendationsBox.scss
 delete mode 100644 src/client/views/RecommendationsBox.tsx

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

diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts
index 7578b7df0..985fcce11 100644
--- a/src/client/documents/DocumentTypes.ts
+++ b/src/client/documents/DocumentTypes.ts
@@ -36,6 +36,5 @@ export enum DocumentType {
 
     LINKDB = "linkdb",          // database of links  ??? why do we have this
     SCRIPTDB = "scriptdb",          // database of scripts
-    RECOMMENDATION = "recommendation", // view of a recommendation
     GROUPDB = "groupdb"         // database of groups
 }
\ No newline at end of file
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 7e094089f..984d43e32 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -45,7 +45,6 @@ import { SliderBox } from "../views/nodes/SliderBox";
 import { VideoBox } from "../views/nodes/VideoBox";
 import { WebBox } from "../views/nodes/WebBox";
 import { PresElementBox } from "../views/presentationview/PresElementBox";
-import { RecommendationsBox } from "../views/RecommendationsBox";
 import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo";
 import { DocumentType } from "./DocumentTypes";
 import { Networking } from "../Network";
@@ -301,10 +300,6 @@ export namespace Docs {
                 layout: { view: FontIconBox, dataField: defaultDataKey },
                 options: { _width: 40, _height: 40, borderRounding: "100%" },
             }],
-            [DocumentType.RECOMMENDATION, {
-                layout: { view: RecommendationsBox, dataField: defaultDataKey },
-                options: { _width: 200, _height: 200 },
-            }],
             [DocumentType.WEBCAM, {
                 layout: { view: DashWebRTCVideo, dataField: defaultDataKey }
             }],
@@ -805,10 +800,6 @@ export namespace Docs {
             return InstanceFromProto(Prototypes.get(DocumentType.IMPORT), new List<Doc>(), options);
         }
 
-        export function RecommendationsDocument(data: Doc[], options: DocumentOptions = {}) {
-            return InstanceFromProto(Prototypes.get(DocumentType.RECOMMENDATION), new List<Doc>(data), options);
-        }
-
         export type DocConfig = {
             doc: Doc,
             initialWidth?: number,
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 190dbc8c3..51325ae1b 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -89,7 +89,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
             const transform = (documentView.props.ScreenToLocalTransform().scale(documentView.props.ContentScaling())).inverse();
             var [sptX, sptY] = transform.transformPoint(0, 0);
             let [bptX, bptY] = transform.transformPoint(documentView.props.PanelWidth(), documentView.props.PanelHeight());
-            if (StrCast(Doc.Layout(documentView.props.Document).layout).includes("LinkAnchorBox")) {
+            if (documentView.props.LayoutTemplateString?.includes("LinkAnchorBox")) {
                 const docuBox = documentView.ContentDiv.getElementsByClassName("linkAnchorBox-cont");
                 if (docuBox.length) {
                     const rect = docuBox[0].getBoundingClientRect();
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 086085db5..c9f95a538 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -105,7 +105,6 @@ export default class KeyManager {
                 }
                 doDeselect && SelectionManager.DeselectAll();
                 DictationManager.Controls.stop();
-                // RecommendationsBox.Instance.closeMenu();
                 GoogleAuthenticationManager.Instance.cancel();
                 HypothesisAuthenticationManager.Instance.cancel();
                 SharingManager.Instance.close();
diff --git a/src/client/views/RecommendationsBox.scss b/src/client/views/RecommendationsBox.scss
deleted file mode 100644
index 7d89042a4..000000000
--- a/src/client/views/RecommendationsBox.scss
+++ /dev/null
@@ -1,69 +0,0 @@
-@import "globalCssVariables";
-
-.rec-content *{
-    display: inline-block;
-    margin: auto;
-    width: 50;
-    height: 150px;
-    border: 1px dashed grey;
-    padding: 10px 10px;
-}
-
-.rec-content {
-    float: left;
-    width: inherit;
-    align-content: center;
-}
-
-.rec-scroll {
-    overflow-y: scroll;
-    overflow-x: hidden;
-    position: absolute;
-    pointer-events: all;
-    // display: flex;
-    z-index: 10000;
-    box-shadow: gray 0.2vw 0.2vw 0.4vw;
-    // flex-direction: column;
-    background: whitesmoke;
-    padding-bottom: 10px;
-    padding-top: 20px;
-    // border-radius: 15px;
-    border: solid #BBBBBBBB 1px;
-    width: 100%;
-    text-align: center;
-    // max-height: 250px;
-    height: 100%;
-    text-transform: uppercase;
-    color: grey;
-    letter-spacing: 2px;
-}
-
-.content {
-    padding: 10px;
-    display: flex;
-    flex-direction: row;
-    align-items: center;
-    justify-content: center;
-}
-
-.image-background {
-    pointer-events: none;
-    background-color: transparent;
-    width: 50%;
-    text-align: center;
-    margin-left: 5px;
-}
-
-// bcz: UGH!!  Can't have global settings like this!!!
-// img{
-//     width: 100%;
-//     height: 100%;
-// }
-
-.score {
-    // margin-left: 15px;
-    width: 50%;
-    height: 100%;
-    text-align: center;
-    margin-left: 10px;
-}
diff --git a/src/client/views/RecommendationsBox.tsx b/src/client/views/RecommendationsBox.tsx
deleted file mode 100644
index 196151e32..000000000
--- a/src/client/views/RecommendationsBox.tsx
+++ /dev/null
@@ -1,201 +0,0 @@
-import { observer } from "mobx-react";
-import React = require("react");
-import { observable, action, computed, runInAction } from "mobx";
-import Measure from "react-measure";
-import "./RecommendationsBox.scss";
-import { Doc, DocListCast, WidthSym, HeightSym } from "../../fields/Doc";
-import { DocumentIcon } from "./nodes/DocumentIcon";
-import { StrCast, NumCast } from "../../fields/Types";
-import { returnFalse, emptyFunction, returnEmptyString, returnOne, emptyPath, returnZero, returnEmptyFilter } from "../../Utils";
-import { Transform } from "../util/Transform";
-import { ObjectField } from "../../fields/ObjectField";
-import { DocumentView } from "./nodes/DocumentView";
-import { DocumentType } from '../documents/DocumentTypes';
-import { ClientRecommender } from "../ClientRecommender";
-import { DocServer } from "../DocServer";
-import { Id } from "../../fields/FieldSymbols";
-import { FieldView, FieldViewProps } from "./nodes/FieldView";
-import { DocumentManager } from "../util/DocumentManager";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { library } from "@fortawesome/fontawesome-svg-core";
-import { faBullseye, faLink } from "@fortawesome/free-solid-svg-icons";
-import { DocUtils } from "../documents/Documents";
-
-export interface RecProps {
-    documents: { preview: Doc, similarity: number }[];
-    node: Doc;
-}
-
-library.add(faBullseye, faLink);
-
-@observer
-export class RecommendationsBox extends React.Component<FieldViewProps> {
-
-    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(RecommendationsBox, fieldKey); }
-
-    // @observable private _display: boolean = false;
-    @observable private _pageX: number = 0;
-    @observable private _pageY: number = 0;
-    @observable private _width: number = 0;
-    @observable private _height: number = 0;
-    @observable.shallow private _docViews: JSX.Element[] = [];
-    // @observable private _documents: { preview: Doc, score: number }[] = [];
-    private previewDocs: Doc[] = [];
-
-    constructor(props: FieldViewProps) {
-        super(props);
-    }
-
-    @action
-    private DocumentIcon(doc: Doc) {
-        const layoutresult = StrCast(doc.type);
-        let renderDoc = doc;
-        //let box: number[] = [];
-        if (layoutresult.indexOf(DocumentType.COL) !== -1) {
-            renderDoc = Doc.MakeDelegate(renderDoc);
-        }
-        const returnXDimension = () => 150;
-        const returnYDimension = () => 150;
-        const scale = () => returnXDimension() / NumCast(renderDoc._nativeWidth, returnXDimension());
-        //let scale = () => 1;
-        const newRenderDoc = Doc.MakeAlias(renderDoc); ///   newRenderDoc -> renderDoc -> render"data"Doc -> TextProt
-        newRenderDoc.height = NumCast(this.props.Document.documentIconHeight);
-        newRenderDoc.autoHeight = false;
-        const docview = <div>
-            <DocumentView
-                fitToBox={StrCast(doc.type).indexOf(DocumentType.COL) !== -1}
-                Document={newRenderDoc}
-                addDocument={returnFalse}
-                LibraryPath={emptyPath}
-                removeDocument={returnFalse}
-                rootSelected={returnFalse}
-                ScreenToLocalTransform={Transform.Identity}
-                addDocTab={returnFalse}
-                pinToPres={returnFalse}
-                renderDepth={1}
-                NativeHeight={returnZero}
-                NativeWidth={returnZero}
-                PanelWidth={returnXDimension}
-                PanelHeight={returnYDimension}
-                focus={emptyFunction}
-                backgroundColor={returnEmptyString}
-                parentActive={returnFalse}
-                whenActiveChanged={returnFalse}
-                bringToFront={emptyFunction}
-                docFilters={returnEmptyFilter}
-                ContainingCollectionView={undefined}
-                ContainingCollectionDoc={undefined}
-                ContentScaling={scale}
-            />
-        </div>;
-        return docview;
-
-    }
-
-    // @action
-    // closeMenu = () => {
-    //     this._display = false;
-    //     this.previewDocs.forEach(doc => DocServer.DeleteDocument(doc[Id]));
-    //     this.previewDocs = [];
-    // }
-
-    // @action
-    // resetDocuments = () => {
-    //     this._documents = [];
-    // }
-
-    // @action
-    // displayRecommendations(x: number, y: number) {
-    //     this._pageX = x;
-    //     this._pageY = y;
-    //     this._display = true;
-    // }
-
-    static readonly buffer = 20;
-
-    // get pageX() {
-    //     const x = this._pageX;
-    //     if (x < 0) {
-    //         return 0;
-    //     }
-    //     const width = this._width;
-    //     if (x + width > window.innerWidth - RecommendationsBox.buffer) {
-    //         return window.innerWidth - RecommendationsBox.buffer - width;
-    //     }
-    //     return x;
-    // }
-
-    // get pageY() {
-    //     const y = this._pageY;
-    //     if (y < 0) {
-    //         return 0;
-    //     }
-    //     const height = this._height;
-    //     if (y + height > window.innerHeight - RecommendationsBox.buffer) {
-    //         return window.innerHeight - RecommendationsBox.buffer - height;
-    //     }
-    //     return y;
-    // }
-
-    // get createDocViews() {
-    //     return DocListCast(this.props.Document.data).map(doc => {
-    //         return (
-    //             <div className="content">
-    //                 <span style={{ height: NumCast(this.props.Document.documentIconHeight) }} className="image-background">
-    //                     {this.DocumentIcon(doc)}
-    //                 </span>
-    //                 <span className="score">{NumCast(doc.score).toFixed(4)}</span>
-    //                 <div style={{ marginRight: 50 }} onClick={() => DocumentManager.Instance.jumpToDocument(doc, false)}>
-    //                     <FontAwesomeIcon className="documentdecorations-icon" icon={"bullseye"} size="sm" />
-    //                 </div>
-    //                 <div style={{ marginRight: 50 }} onClick={() => DocUtils.MakeLink({ doc: this.props.Document.sourceDoc as Doc }, { doc: doc }, "User Selected Link", "Generated from Recommender", undefined)}>
-    //                     <FontAwesomeIcon className="documentdecorations-icon" icon={"link"} size="sm" />
-    //                 </div>
-    //             </div>
-    //         );
-    //     });
-    // }
-
-    componentDidMount() { //TODO: invoking a computedFn from outside an reactive context won't be memoized, unless keepAlive is set
-        runInAction(() => {
-            if (this._docViews.length === 0) {
-                this._docViews = DocListCast(this.props.Document.data).map(doc => {
-                    return (
-                        <div className="content">
-                            <span style={{ height: NumCast(this.props.Document.documentIconHeight) }} className="image-background">
-                                {this.DocumentIcon(doc)}
-                            </span>
-                            <span className="score">{NumCast(doc.score).toFixed(4)}</span>
-                            <div style={{ marginRight: 50 }} onClick={() => DocumentManager.Instance.jumpToDocument(doc, false)}>
-                                <FontAwesomeIcon className="documentdecorations-icon" icon={"bullseye"} size="sm" />
-                            </div>
-                            <div style={{ marginRight: 50 }} onClick={() => DocUtils.MakeLink({ doc: this.props.Document.sourceDoc as Doc }, { doc: doc }, "Recommender", "", undefined)}>
-                                <FontAwesomeIcon className="documentdecorations-icon" icon={"link"} size="sm" />
-                            </div>
-                        </div>
-                    );
-                });
-            }
-        });
-    }
-
-    render() { //TODO: Invariant violation: max depth exceeded error. Occurs when images are rendered. 
-        // if (!this._display) {
-        //     return null;
-        // }
-        // let style = { left: this.pageX, top: this.pageY };
-        //const transform = "translate(" + (NumCast(this.props.node.x) + 350) + "px, " + NumCast(this.props.node.y) + "px"
-        let title = StrCast((this.props.Document.sourceDoc as Doc).title);
-        if (title.length > 15) {
-            title = title.substring(0, 15) + "...";
-        }
-        return (
-            <div className="rec-scroll">
-                <p>Recommendations for "{title}"</p>
-                {this._docViews}
-            </div>
-        );
-    }
-    // 
-    // 
-}
\ No newline at end of file
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index 9fb8a227e..ebaf2cfcb 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -64,11 +64,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
     }
 
     toggleFloat = (e: React.ChangeEvent<HTMLInputElement>): void => {
-        SelectionManager.DeselectAll();
-        const topDocView = this.props.docViews[0];
-        const ex = e.target.getBoundingClientRect().left;
-        const ey = e.target.getBoundingClientRect().top;
-        DocumentView.FloatDoc(topDocView, ex, ey);
+        DocumentView.FloatDoc(this.props.docViews[0]);
     }
 
     toggleAudio = (e: React.ChangeEvent<HTMLInputElement>): void => {
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index d6cb79e9c..8813861d2 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -313,7 +313,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
                 <div className="collectionMenu">
                     <div className="collectionViewBaseChrome">
                         {this.props.type === CollectionViewType.Invalid || this.props.type === CollectionViewType.Docking ? (null) : this.viewModes}
-                        {this.props.type === CollectionViewType.Invalid || this.props.type === CollectionViewType.Docking ? (null) : this.templateChrome}
+                        {this.props.type === CollectionViewType.Docking ? (null) : this.templateChrome}
                         <div className="collectionViewBaseChrome-viewSpecs" title="filter documents to show" style={{ display: "grid" }}>
                             <button className={"antimodeMenu-button"} onClick={this.toggleViewSpecs} >
                                 <FontAwesomeIcon icon="filter" size="lg" />
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index a89fcc703..9f78c15eb 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -127,7 +127,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
 
             const docs = rawdocs.filter(d => !(d instanceof Promise)).map(d => d as Doc);
             const docFilters = this.docFilters();
-            const viewSpecScript = Cast(this.props.Document.viewSpecScript, ScriptField);
+            const viewSpecScript = ScriptCast(this.props.Document.viewSpecScript);
             const docRangeFilters = this.props.ignoreFields?.includes("_docRangeFilters") ? [] : Cast(this.props.Document._docRangeFilters, listSpec("string"), []);
 
             return this.props.Document.dontRegisterView ? docs : DocUtils.FilterDocs(docs, docFilters, docRangeFilters, viewSpecScript);
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 651357e5d..705871a6f 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -100,8 +100,8 @@ class TreeView extends React.Component<TreeViewProps> {
     childDocList(field: string) {
         const layout = Doc.LayoutField(this.doc) instanceof Doc ? Doc.LayoutField(this.doc) as Doc : undefined;
         return ((this.props.dataDoc ? DocListCast(this.props.dataDoc[field]) : undefined) || // if there's a data doc for an expanded template, use it's data field
-            (layout ? Cast(layout[field], listSpec(Doc)) : undefined) || // else if there's a layout doc, display it's fields
-            Cast(this.doc[field], listSpec(Doc))) as Doc[]; // otherwise use the document's data field
+            (layout ? DocListCast(layout[field]) : undefined) || // else if there's a layout doc, display it's fields
+            DocListCast(this.doc[field])) as Doc[]; // otherwise use the document's data field
     }
     @computed get childDocs() { return this.childDocList(this.fieldKey); }
     @computed get childLinks() { return this.childDocList("links"); }
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 47dc0a773..e8173d103 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -35,7 +35,6 @@ import { VideoBox } from "./VideoBox";
 import { WebBox } from "./WebBox";
 import { InkingStroke } from "../InkingStroke";
 import React = require("react");
-import { RecommendationsBox } from "../RecommendationsBox";
 import { TraceMobx, GetEffectiveAcl } from "../../../fields/util";
 import { ScriptField } from "../../../fields/ScriptField";
 import XRegExp = require("xregexp");
@@ -194,7 +193,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
                     CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox,
                     PDFBox, VideoBox, AudioBox, PresBox, YoutubeBox, PresElementBox, QueryBox,
                     ColorBox, DashWebRTCVideo, LinkAnchorBox, InkingStroke, DocHolderBox, LinkBox, ScriptingBox,
-                    RecommendationsBox, ScreenshotBox, HTMLtag, ComparisonBox
+                    ScreenshotBox, HTMLtag, ComparisonBox
                 }}
                 bindings={bindings}
                 jsx={layoutFrame}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index c47edefd6..15cf9556b 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -238,20 +238,28 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         }
     }
 
-    public static FloatDoc(topDocView: DocumentView, x: number, y: number) {
+    @undoBatch @action
+    public static FloatDoc(topDocView: DocumentView, x?: number, y?: number) {
         const topDoc = topDocView.props.Document;
-        const de = new DragManager.DocumentDragData([topDoc]);
-        de.dragDivName = topDocView.props.dragDivName;
-        de.moveDocument = topDocView.props.moveDocument;
-        setTimeout(() => {
-            const newDocView = DocumentManager.Instance.getDocumentView(topDoc);
-            if (newDocView) {
-                const contentDiv = newDocView.ContentDiv!;
-                const xf = contentDiv.getBoundingClientRect();
-                DragManager.StartDocumentDrag([contentDiv], de, x, y, { offsetX: x - xf.left, offsetY: y - xf.top, hideSource: true });
+        const container = topDocView.props.ContainingCollectionView;
+        if (container) {
+            SelectionManager.DeselectAll();
+            if (topDoc.z && (x === undefined && y === undefined)) {
+                const spt = container.screenToLocalTransform().inverse().transformPoint(NumCast(topDoc.x), NumCast(topDoc.y));
+                topDoc.z = 0;
+                topDoc.x = spt[0];
+                topDoc.y = spt[1];
+                topDocView.props.removeDocument?.(topDoc);
+                topDocView.props.addDocTab(topDoc, "inParent");
+            } else {
+                const spt = topDocView.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
+                const fpt = container.screenToLocalTransform().transformPoint(x !== undefined ? x : spt[0], y !== undefined ? y : spt[1]);
+                topDoc.z = 1;
+                topDoc.x = fpt[0];
+                topDoc.y = fpt[1];
             }
-        }, 0);
-        UndoManager.RunInBatch(action(() => topDoc.z = topDoc.z ? 0 : 1), "float");
+            setTimeout(() => SelectionManager.SelectDoc(DocumentManager.Instance.getDocumentView(topDoc, container)!, false), 0);
+        }
     }
 
     onKeyDown = (e: React.KeyboardEvent) => {
@@ -849,6 +857,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         if (this.props.LayoutTemplateString?.includes("LinkAnchorBox")) return null;
         return (this.props.treeViewDoc && this.props.LayoutTemplateString) || // render nothing for: tree view anchor dots
             this.layoutDoc.presBox ||  // presentationbox nodes
+            this.rootDoc.type === DocumentType.LINK ||
             this.props.dontRegisterView ? (null) : // view that are not registered
             DocUtils.FilterDocs(this.directLinks, this.props.docFilters(), []).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) =>
                 <DocumentView {...this.props} key={i + 1}
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index d4ab70200..e02ea61f7 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -54,9 +54,9 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps, LinkAnch
                 const dragData = new DragManager.DocumentDragData([this.rootDoc]);
                 dragData.dropAction = "alias";
                 dragData.removeDropProperties = ["anchor1_x", "anchor1_y", "anchor2_x", "anchor2_y", "isLinkButton"];
-                DragManager.StartDocumentDrag([this._ref.current!], dragData, down[0], down[1]);
+                DragManager.StartDocumentDrag([this._ref.current!], dragData, pt[0], pt[1]);
                 return true;
-            } else if (dragdist > separation) {
+            } else {
                 this.rootDoc[this.fieldKey + "_x"] = (pt[0] - bounds.left) / bounds.width * 100;
                 this.rootDoc[this.fieldKey + "_y"] = (pt[1] - bounds.top) / bounds.height * 100;
             }
-- 
cgit v1.2.3-70-g09d2


From f1f370c43de775f27c08b52bf3b6de310c6d2cda Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 30 Jul 2020 11:04:58 -0400
Subject: added "float" option to the main toolbar for documentviews

---
 src/client/views/MainView.tsx                   |  4 ++--
 src/client/views/collections/CollectionMenu.tsx | 10 +++++++++-
 2 files changed, 11 insertions(+), 3 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 37d99fb16..bb73df75c 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -1,5 +1,5 @@
 import { library } from '@fortawesome/fontawesome-svg-core';
-import { faHireAHelper } from '@fortawesome/free-brands-svg-icons';
+import { faHireAHelper, faBuffer } from '@fortawesome/free-brands-svg-icons';
 import * as fa from '@fortawesome/free-solid-svg-icons';
 import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -148,7 +148,7 @@ export class MainView extends React.Component {
             fa.faEye, fa.faArrowsAlt, fa.faQuoteLeft, fa.faSortAmountDown, fa.faAlignLeft, fa.faAlignCenter, fa.faAlignRight, fa.faHeading, fa.faRulerCombined,
             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.faBezierCurve, fa.faCircle, fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight);
+            fa.faBezierCurve, fa.faCircle, fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer);
         this.initEventListeners();
         this.initAuthenticationRouters();
     }
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 8813861d2..da4c131cb 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -27,6 +27,7 @@ import { ColorState } from "react-color";
 import { ObjectField } from "../../../fields/ObjectField";
 import { ScriptField } from "../../../fields/ScriptField";
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
+import { DocUtils } from "../../documents/Documents";
 
 @observer
 export default class CollectionMenu extends AntimodeMenu {
@@ -540,7 +541,14 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
                 <FontAwesomeIcon icon={"caret-right"} size={"lg"} />
             </div>
 
-            {!this.props.isOverlay ? (null) :
+            {<button className={"antimodeMenu-button"} key="float"
+                style={{ backgroundColor: !this.props.docView.layoutDoc.isAnnotating ? "121212" : undefined, borderRight: "1px solid gray" }}
+                title="Toggle Overlay Layer"
+                onClick={() => DocumentView.FloatDoc(this.props.docView)}>
+                <FontAwesomeIcon icon={["fab", "buffer"]} size={"lg"} />
+            </button>}
+            
+            {!this.props.isOverlay || this.document.type !== DocumentType.WEB ? (null) :
                 <button className={"antimodeMenu-button"} key="hypothesis"
                     style={{ backgroundColor: !this.props.docView.layoutDoc.isAnnotating ? "121212" : undefined, borderRight: "1px solid gray" }}
                     title="Use Hypothesis"
-- 
cgit v1.2.3-70-g09d2


From a9ec139961b0262698851cd7e2dd3430a0acddd7 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 30 Jul 2020 11:11:21 -0400
Subject: from last

---
 src/client/views/TemplateMenu.tsx               |  5 -----
 src/client/views/collections/CollectionMenu.tsx | 14 +++++++-------
 2 files changed, 7 insertions(+), 12 deletions(-)

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

diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index ebaf2cfcb..eb20fc257 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -63,10 +63,6 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
         this.props.docViews.map(dv => dv.switchViews(false, "layout"));
     }
 
-    toggleFloat = (e: React.ChangeEvent<HTMLInputElement>): void => {
-        DocumentView.FloatDoc(this.props.docViews[0]);
-    }
-
     toggleAudio = (e: React.ChangeEvent<HTMLInputElement>): void => {
         this.props.docViews.map(dv => dv.props.Document._showAudio = e.target.checked);
     }
@@ -123,7 +119,6 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
         this.props.templates.forEach((checked, template) =>
             templateMenu.push(<TemplateToggle key={template.Name} template={template} checked={checked} toggle={this.toggleTemplate} />));
         templateMenu.push(<OtherToggle key={"audio"} name={"Audio"} checked={firstDoc._showAudio ? true : false} toggle={this.toggleAudio} />);
-        templateMenu.push(<OtherToggle key={"float"} name={"Float"} checked={firstDoc.z ? true : false} toggle={this.toggleFloat} />);
         templateMenu.push(<OtherToggle key={"chrome"} name={"Chrome"} checked={layout._chromeStatus !== "disabled"} toggle={this.toggleChrome} />);
         templateMenu.push(<OtherToggle key={"default"} name={"Default"} checked={templateName === "layout"} toggle={this.toggleDefault} />);
         addedTypes.concat(noteTypes).map(template => template.treeViewChecked = this.templateIsUsed(firstDoc, template));
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index da4c131cb..0ca86172f 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -320,6 +320,13 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp
                                 <FontAwesomeIcon icon="filter" size="lg" />
                             </button>
                         </div>
+
+                        {this.props.docView.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform ? (null) : <button className={"antimodeMenu-button"} key="float"
+                            style={{ backgroundColor: !this.props.docView.layoutDoc.isAnnotating ? "121212" : undefined, borderRight: "1px solid gray" }}
+                            title="Toggle Overlay Layer"
+                            onClick={() => DocumentView.FloatDoc(this.props.docView)}>
+                            <FontAwesomeIcon icon={["fab", "buffer"]} size={"lg"} />
+                        </button>}
                     </div>
                     {this.subChrome}
                 </div>
@@ -541,13 +548,6 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionMenu
                 <FontAwesomeIcon icon={"caret-right"} size={"lg"} />
             </div>
 
-            {<button className={"antimodeMenu-button"} key="float"
-                style={{ backgroundColor: !this.props.docView.layoutDoc.isAnnotating ? "121212" : undefined, borderRight: "1px solid gray" }}
-                title="Toggle Overlay Layer"
-                onClick={() => DocumentView.FloatDoc(this.props.docView)}>
-                <FontAwesomeIcon icon={["fab", "buffer"]} size={"lg"} />
-            </button>}
-            
             {!this.props.isOverlay || this.document.type !== DocumentType.WEB ? (null) :
                 <button className={"antimodeMenu-button"} key="hypothesis"
                     style={{ backgroundColor: !this.props.docView.layoutDoc.isAnnotating ? "121212" : undefined, borderRight: "1px solid gray" }}
-- 
cgit v1.2.3-70-g09d2

