From da192a9f580174e3b452079026e70d5c08d8a90f Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Fri, 23 Aug 2019 16:11:23 -0400
Subject: added start of an overlay for documents.

---
 src/client/views/OverlayView.tsx | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

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

diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 2f2579057..a60dc591c 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -1,9 +1,15 @@
 import * as React from "react";
 import { observer } from "mobx-react";
 import { observable, action } from "mobx";
-import { Utils } from "../../Utils";
+import { Utils, emptyFunction, returnOne, returnTrue, returnEmptyString } from "../../Utils";
 
 import './OverlayView.scss';
+import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils";
+import { DocListCast, Doc } from "../../new_fields/Doc";
+import { Id } from "../../new_fields/FieldSymbols";
+import { DocumentView } from "./nodes/DocumentView";
+import { Transform } from "../util/Transform";
+import { CollectionFreeFormDocumentView } from "./nodes/CollectionFreeFormDocumentView";
 
 export type OverlayDisposer = () => void;
 
@@ -134,8 +140,29 @@ export class OverlayView extends React.Component {
 
     render() {
         return (
-            <div>
+            <div className="overlayView">
                 {this._elements}
+                {CurrentUserUtils.UserDocument.overlays instanceof Doc && DocListCast(CurrentUserUtils.UserDocument.overlays.data).map(d => (
+                    <CollectionFreeFormDocumentView key={d[Id]}
+                        Document={d}
+                        bringToFront={emptyFunction}
+                        addDocument={undefined}
+                        removeDocument={undefined}
+                        ContentScaling={returnOne}
+                        PanelWidth={returnOne}
+                        PanelHeight={returnOne}
+                        ScreenToLocalTransform={Transform.Identity}
+                        renderDepth={1}
+                        selectOnLoad={false}
+                        parentActive={returnTrue}
+                        whenActiveChanged={emptyFunction}
+                        focus={emptyFunction}
+                        backgroundColor={returnEmptyString}
+                        addDocTab={emptyFunction}
+                        pinToPres={emptyFunction}
+                        ContainingCollectionView={undefined}
+                        zoomToScale={emptyFunction}
+                        getScale={returnOne} />))}
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From b4f79e48d5d30312367e268c2c505f65c5cacdb4 Mon Sep 17 00:00:00 2001
From: monikahedman <monika_hedman@brown.edu>
Date: Tue, 27 Aug 2019 13:19:20 -0400
Subject: things are progressing

---
 src/client/views/MainView.tsx               | 30 ++++++++++++++++++-----------
 src/client/views/OverlayView.tsx            |  2 +-
 src/client/views/linking/LinkFollowBox.scss |  1 +
 src/client/views/linking/LinkFollowBox.tsx  | 12 +++++++++++-
 4 files changed, 32 insertions(+), 13 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index aae67ffb2..b49274e7e 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -12,7 +12,7 @@ import { List } from '../../new_fields/List';
 import { Id } from '../../new_fields/FieldSymbols';
 import { InkTool } from '../../new_fields/InkField';
 import { listSpec } from '../../new_fields/Schema';
-import { BoolCast, Cast, FieldValue, StrCast } from '../../new_fields/Types';
+import { BoolCast, Cast, FieldValue, StrCast, NumCast } from '../../new_fields/Types';
 import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
 import { RouteStore } from '../../server/RouteStore';
 import { emptyFunction, returnOne, returnTrue, Utils, returnEmptyString } from '../../Utils';
@@ -41,6 +41,7 @@ import { FilterBox } from './search/FilterBox';
 import PresModeMenu from './presentationview/PresentationModeMenu';
 import { PresBox } from './nodes/PresBox';
 import { LinkFollowBox } from './linking/LinkFollowBox';
+import { DocumentManager } from '../util/DocumentManager';
 
 @observer
 export class MainView extends React.Component {
@@ -436,14 +437,27 @@ export class MainView extends React.Component {
         }
     }
 
+    toggleLinkFollowBox = () => {
+        if (LinkFollowBox.Instance) {
+            console.log("is instance!")
+            // if (LinkFollowBox.Instance.props && LinkFollowBox.Instance.props.removeDocument) LinkFollowBox.Instance.props.removeDocument(LinkFollowBox.Instance.props.Document);
+        }
+        else {
+            let overlayView = document.getElementById("overlayView");
+            let overlayWidth = 0;
+            if (overlayView) overlayWidth = overlayView.offsetWidth;
+            let x: number = overlayWidth - 500;
+            let doc = Docs.Create.LinkFollowBoxDocument({ x: x, y: 20, width: 500, height: 370, title: "Link Follower" });
+            Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc);
+        }
+    }
+
     @observable private _colorPickerDisplay = false;
     /* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */
     nodesMenu() {
-
         let imgurl = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg";
 
         let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" }));
-        let addLinkFollowBox = action(() => Docs.Create.LinkFollowBoxDocument({ width: 500, height: 370, title: "Link Follower" }));
         let addPresNode = action(() => Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List<Doc>(), { width: 200, height: 500, title: "a presentation trail" }));
         let addWebNode = action(() => Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" }));
         let addDragboxNode = action(() => Docs.Create.DragboxDocument({ width: 40, height: 40, title: "drag collection" }));
@@ -459,7 +473,7 @@ export class MainView extends React.Component {
             [React.createRef<HTMLDivElement>(), "globe-asia", "Add Website", addWebNode],
             [React.createRef<HTMLDivElement>(), "bolt", "Add Button", addButtonDocument],
             [React.createRef<HTMLDivElement>(), "file", "Add Document Dragger", addDragboxNode],
-            [React.createRef<HTMLDivElement>(), "link", "Open Link Follow Box", addLinkFollowBox],
+            // [React.createRef<HTMLDivElement>(), "link", "Open Link Follow Box", addLinkFollowBox],
             [React.createRef<HTMLDivElement>(), "cloud-upload-alt", "Import Directory", addImportCollectionNode], //remove at some point in favor of addImportCollectionNode
             //[React.createRef<HTMLDivElement>(), "play", "Add Youtube Searcher", addYoutubeSearcher],
         ];
@@ -481,6 +495,7 @@ export class MainView extends React.Component {
                                 <FontAwesomeIcon icon={btn[1]} size="sm" />
                             </button>
                         </div></li>)}
+                    <li key="linkFollow"><button className="add-button round-button" title="Open Link Follower" onClick={this.toggleLinkFollowBox}><FontAwesomeIcon icon="link" size="sm" /></button></li>
                     <li key="color"><button className="add-button round-button" title="Select Color" style={{ zIndex: 1000 }} onClick={() => this.toggleColorPicker()}><div className="toolbar-color-button" style={{ backgroundColor: InkingControl.Instance.selectedColor }} >
                         <div className="toolbar-color-picker" onClick={this.onColorClick} style={this._colorPickerDisplay ? { color: "black", display: "block" } : { color: "black", display: "none" }}>
                             <SketchPicker color={InkingControl.Instance.selectedColor} onChange={InkingControl.Instance.switchColor} />
@@ -503,12 +518,6 @@ export class MainView extends React.Component {
         this._colorPickerDisplay = close ? false : !this._colorPickerDisplay;
     }
 
-    @action
-    toggleLinkFollowBox = () => {
-        console.log("toggling link editor")
-        this._linkFollowBox = !this._linkFollowBox;
-    }
-
     /* @TODO this should really be moved into a moveable toolbar component, but for now let's put it here to meet the deadline */
     @computed
     get miscButtons() {
@@ -517,7 +526,6 @@ export class MainView extends React.Component {
         return [
             this.isSearchVisible ? <div className="main-searchDiv" key="search" style={{ top: '34px', right: '1px', position: 'absolute' }} > <FilterBox /> </div> : null,
             <div className="main-buttonDiv" key="logout" style={{ bottom: '0px', right: '1px', position: 'absolute' }} ref={logoutRef}>
-                <button onClick={this.toggleLinkFollowBox}>Open Link Editor</button>
                 <button onClick={() => window.location.assign(Utils.prepend(RouteStore.logout))}>Log Out</button></div>
         ];
 
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index a60dc591c..8d80ad1f1 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -140,7 +140,7 @@ export class OverlayView extends React.Component {
 
     render() {
         return (
-            <div className="overlayView">
+            <div className="overlayView" id="overlayView">
                 {this._elements}
                 {CurrentUserUtils.UserDocument.overlays instanceof Doc && DocListCast(CurrentUserUtils.UserDocument.overlays.data).map(d => (
                     <CollectionFreeFormDocumentView key={d[Id]}
diff --git a/src/client/views/linking/LinkFollowBox.scss b/src/client/views/linking/LinkFollowBox.scss
index 7fad9ae93..a34285727 100644
--- a/src/client/views/linking/LinkFollowBox.scss
+++ b/src/client/views/linking/LinkFollowBox.scss
@@ -8,6 +8,7 @@
     box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw;
     border: solid #BBBBBBBB 5px;
     pointer-events: all;
+    // transform-origin: top right;
     // overflow: hidden;
 
     .linkFollowBox-header {
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index 213022bc8..cf44ae649 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -16,6 +16,7 @@ import { Id } from "../../../new_fields/FieldSymbols";
 import { listSpec } from "../../../new_fields/Schema";
 import { DocServer } from "../../DocServer";
 import { RefField } from "../../../new_fields/RefField";
+import { Docs } from "../../documents/Documents";
 
 enum FollowModes {
     OPENTAB = "Open in Tab",
@@ -59,6 +60,11 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
         this.collectionTypes = ["Invalid", "Freeform", "Schema", "Docking", "Tree", "Stacking", "Masonry"];
     }
 
+    @computed
+    get getDoc() {
+        return this.props.Document;
+    }
+
     componentDidMount = () => {
         this.resetVars();
 
@@ -322,6 +328,10 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
     currentLinkBehavior = () => {
         // this.resetPan();
         if (LinkFollowBox.destinationDoc) {
+            if (this.selectedContextString === "") {
+                this.selectedContextString = "self";
+                this.selectedContext = LinkFollowBox.destinationDoc;
+            }
             if (this.selectedOption === "") this.selectedOption = FollowOptions.NOZOOM;
             let shouldZoom: boolean = this.selectedOption === FollowOptions.NOZOOM ? false : true;
             let notOpenInContext: boolean = this.selectedContextString === "self" || this.selectedContextString === LinkFollowBox.destinationDoc[Id];
@@ -476,7 +486,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
                         type="radio" disabled={LinkFollowBox.linkDoc ? false : true}
                         name="context"
                         value={LinkFollowBox.destinationDoc ? StrCast(LinkFollowBox.destinationDoc[Id]) : "self"}
-                        checked={LinkFollowBox.destinationDoc ? this.selectedContextString === StrCast(LinkFollowBox.destinationDoc[Id]) : this.selectedContextString === "self"}
+                        checked={LinkFollowBox.destinationDoc ? this.selectedContextString === StrCast(LinkFollowBox.destinationDoc[Id]) || this.selectedContextString === "self" : true}
                         onChange={this.handleContextChange} />
                         Open Self
                 </label><br />
-- 
cgit v1.2.3-70-g09d2


From 34e0b1cf34474ec6765e212b6a35defefbfb49c9 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Tue, 27 Aug 2019 15:46:03 -0400
Subject: removed selectOnLoad prop.  fixed textboxes from deselecting on
 carriage return.

---
 src/client/views/MainOverlayTextBox.tsx                    |  2 +-
 src/client/views/MainView.tsx                              |  2 --
 src/client/views/OverlayView.tsx                           |  1 -
 src/client/views/collections/CollectionDockingView.tsx     |  1 -
 src/client/views/collections/CollectionSchemaCells.tsx     |  1 -
 src/client/views/collections/CollectionSchemaView.tsx      |  1 -
 .../collectionFreeForm/CollectionFreeFormView.tsx          | 14 +++-----------
 src/client/views/nodes/DocumentView.tsx                    |  4 +---
 src/client/views/nodes/FieldView.tsx                       |  2 --
 src/client/views/nodes/FormattedTextBox.tsx                |  9 ++++++---
 src/client/views/nodes/KeyValuePair.tsx                    |  1 -
 src/client/views/presentationview/PresentationElement.tsx  |  1 -
 src/client/views/search/SearchItem.tsx                     |  1 -
 13 files changed, 11 insertions(+), 29 deletions(-)

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

diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx
index 65a291d99..f15b60347 100644
--- a/src/client/views/MainOverlayTextBox.tsx
+++ b/src/client/views/MainOverlayTextBox.tsx
@@ -156,7 +156,7 @@ export class MainOverlayTextBox extends React.Component<MainOverlayTextBoxProps>
                                 DataDoc={FormattedTextBox.InputBoxOverlay.props.DataDoc}
                                 onClick={undefined}
                                 ChromeHeight={this.ChromeHeight}
-                                isSelected={returnTrue} select={emptyFunction} renderDepth={0} selectOnLoad={true}
+                                isSelected={returnTrue} select={emptyFunction} renderDepth={0}
                                 ContainingCollectionView={undefined} whenActiveChanged={emptyFunction} active={returnTrue} ContentScaling={returnOne}
                                 ScreenToLocalTransform={this._textXf} PanelWidth={returnZero} PanelHeight={returnZero} focus={emptyFunction}
                                 pinToPres={returnZero} addDocTab={this.addDocTab} outer_div={(tooltip: HTMLElement) => { this._tooltip = tooltip; this.updateTooltip(); }} />
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index a02214deb..6b856443b 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -326,7 +326,6 @@ export class MainView extends React.Component {
                             PanelHeight={this.getPHeight}
                             renderDepth={0}
                             backgroundColor={returnEmptyString}
-                            selectOnLoad={false}
                             focus={emptyFunction}
                             parentActive={returnTrue}
                             whenActiveChanged={emptyFunction}
@@ -389,7 +388,6 @@ export class MainView extends React.Component {
             PanelWidth={this.flyoutWidthFunc}
             PanelHeight={this.getPHeight}
             renderDepth={0}
-            selectOnLoad={false}
             focus={emptyFunction}
             backgroundColor={returnEmptyString}
             parentActive={returnTrue}
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index a60dc591c..538614089 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -153,7 +153,6 @@ export class OverlayView extends React.Component {
                         PanelHeight={returnOne}
                         ScreenToLocalTransform={Transform.Identity}
                         renderDepth={1}
-                        selectOnLoad={false}
                         parentActive={returnTrue}
                         whenActiveChanged={emptyFunction}
                         focus={emptyFunction}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index dc0cbda0b..95f94875c 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -636,7 +636,6 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
             PanelHeight={this.panelHeight}
             ScreenToLocalTransform={this.ScreenToLocalTransform}
             renderDepth={0}
-            selectOnLoad={false}
             parentActive={returnTrue}
             whenActiveChanged={emptyFunction}
             focus={emptyFunction}
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index 551b485e7..9c26a08f0 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -153,7 +153,6 @@ export class CollectionSchemaCell extends React.Component<CellProps> {
             isSelected: returnFalse,
             select: emptyFunction,
             renderDepth: this.props.renderDepth + 1,
-            selectOnLoad: false,
             ScreenToLocalTransform: Transform.Identity,
             focus: emptyFunction,
             active: returnFalse,
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 4008dea51..9d83aa6c1 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -1006,7 +1006,6 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre
                         parentActive={this.props.active}
                         ScreenToLocalTransform={this.getTransform}
                         renderDepth={this.props.renderDepth + 1}
-                        selectOnLoad={false}
                         ContentScaling={this.contentScaling}
                         PanelWidth={this.PanelWidth}
                         PanelHeight={this.PanelHeight}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index f185222ce..62f848a2b 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,7 +1,7 @@
 import { library } from "@fortawesome/fontawesome-svg-core";
 import { faEye } from "@fortawesome/free-regular-svg-icons";
 import { faBraille, faChalkboard, faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faPaintBrush, faTable, faUpload } from "@fortawesome/free-solid-svg-icons";
-import { action, computed, IReactionDisposer, observable, reaction } from "mobx";
+import { action, computed, IReactionDisposer, observable, reaction, trace } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, DocListCastAsync, Field, FieldResult, HeightSym, Opt, WidthSym } from "../../../../new_fields/Doc";
 import { Id } from "../../../../new_fields/FieldSymbols";
@@ -38,6 +38,7 @@ import "./CollectionFreeFormView.scss";
 import { MarqueeView } from "./MarqueeView";
 import React = require("react");
 import { DocServer } from "../../../DocServer";
+import { FormattedTextBox } from "../../nodes/FormattedTextBox";
 
 library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard);
 
@@ -165,8 +166,6 @@ export namespace PivotView {
             return prev;
         }, elements);
 
-        target.resetSelectOnLoaded();
-
         return docViews;
     };
 
@@ -177,7 +176,6 @@ const PanZoomDocument = makeInterface(panZoomSchema, positionSchema, pageSchema)
 
 @observer
 export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
-    private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type)
     private _lastX: number = 0;
     private _lastY: number = 0;
     private get _pwidth() { return this.props.PanelWidth(); }
@@ -241,7 +239,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     private getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth);
     private getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.zoomScaling()).translate(this.panX(), this.panY());
     private addLiveTextBox = (newBox: Doc) => {
-        this._selectOnLoaded = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed
+        FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed
         this.addDocument(newBox, false);
     }
     private addDocument = (newBox: Doc, allowDuplicates: boolean) => {
@@ -642,7 +640,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             onClick: this.props.onClick,
             ScreenToLocalTransform: childLayout.z ? this.getTransformOverlay : this.getTransform,
             renderDepth: this.props.renderDepth + 1,
-            selectOnLoad: childLayout[Id] === this._selectOnLoaded,
             PanelWidth: childLayout[WidthSym],
             PanelHeight: childLayout[HeightSym],
             ContentScaling: returnOne,
@@ -668,7 +665,6 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             onClick: this.props.onClick,
             ScreenToLocalTransform: this.getTransform,
             renderDepth: this.props.renderDepth,
-            selectOnLoad: layoutDoc[Id] === this._selectOnLoaded,
             PanelWidth: layoutDoc[WidthSym],
             PanelHeight: layoutDoc[HeightSym],
             ContentScaling: returnOne,
@@ -768,13 +764,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             return prev;
         }, elements);
 
-        this.resetSelectOnLoaded();
-
         return docviews;
     }
 
-    resetSelectOnLoaded = () => setTimeout(() => this._selectOnLoaded = "", 600);// bcz: surely there must be a better way ....
-
     @computed.struct
     get views() {
         let source = this.elements;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 3cf86b6f9..f7ebfb75a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -92,7 +92,6 @@ export interface DocumentViewProps {
     PanelWidth: () => number;
     PanelHeight: () => number;
     focus: (doc: Doc, willZoom: boolean, scale?: number) => void;
-    selectOnLoad: boolean;
     parentActive: () => boolean;
     whenActiveChanged: (isActive: boolean) => void;
     bringToFront: (doc: Doc, sendToBack?: boolean) => void;
@@ -717,7 +716,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             isSelected={this.isSelected}
             select={this.select}
             onClick={this.onClickHandler}
-            selectOnLoad={this.props.selectOnLoad}
             layoutKey={"layout"}
             fitToBox={BoolCast(this.props.Document.fitToBox) ? true : this.props.fitToBox}
             DataDoc={this.dataDoc} />);
@@ -808,7 +806,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
                         }
                         {!showCaption ? (null) :
                             <div style={{ position: "absolute", bottom: 0, transformOrigin: "bottom left", width: `${100 * this.props.ContentScaling()}%`, transform: `scale(${1 / this.props.ContentScaling()})` }}>
-                                <FormattedTextBox {...this.props} onClick={this.onClickHandler} DataDoc={this.dataDoc} active={returnTrue} isSelected={this.isSelected} focus={emptyFunction} select={this.select} selectOnLoad={this.props.selectOnLoad} fieldExt={""} hideOnLeave={true} fieldKey={showCaption} />
+                                <FormattedTextBox {...this.props} onClick={this.onClickHandler} DataDoc={this.dataDoc} active={returnTrue} isSelected={this.isSelected} focus={emptyFunction} select={this.select} fieldExt={""} hideOnLeave={true} fieldKey={showCaption} />
                             </div>
                         }
                     </div>
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index f0f1b3b73..d9774303b 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -36,7 +36,6 @@ export interface FieldViewProps {
     isSelected: () => boolean;
     select: (isCtrlPressed: boolean) => void;
     renderDepth: number;
-    selectOnLoad: boolean;
     addDocument?: (document: Doc, allowDuplicates?: boolean) => boolean;
     addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
     pinToPres: (document: Doc) => void;
@@ -108,7 +107,6 @@ export class FieldView extends React.Component<FieldViewProps> {
             //         PanelWidth={returnHundred}
             //         PanelHeight={returnHundred}
             //         renderDepth={0} //TODO Why is renderDepth reset?
-            //         selectOnLoad={false}
             //         focus={emptyFunction}
             //         isSelected={this.props.isSelected}
             //         select={returnFalse}
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index acfd2a3b8..c28bf1821 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -622,12 +622,15 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
             }
         }
 
-        if (this.props.selectOnLoad) {
-            if (!this.props.isOverlay) this.props.select(false);
-            else this._editorView!.focus();
+        if (this.props.Document[Id] == FormattedTextBox.SelectOnLoad) {
+            FormattedTextBox.SelectOnLoad = "";
+            this.props.select(false);
         }
+        else if (this.props.isOverlay) this._editorView!.focus();
     }
 
+    public static SelectOnLoad = "";
+
     componentWillUnmount() {
         this._editorView && this._editorView.destroy();
         this._reactionDisposer && this._reactionDisposer();
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 8001b24a7..5afd4d834 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -60,7 +60,6 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
             isSelected: returnFalse,
             select: emptyFunction,
             renderDepth: 1,
-            selectOnLoad: false,
             active: returnFalse,
             whenActiveChanged: emptyFunction,
             ScreenToLocalTransform: Transform.Identity,
diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx
index 83413814f..80aa25f48 100644
--- a/src/client/views/presentationview/PresentationElement.tsx
+++ b/src/client/views/presentationview/PresentationElement.tsx
@@ -359,7 +359,6 @@ export default class PresentationElement extends React.Component<PresentationEle
                     PanelHeight={() => 90}
                     focus={emptyFunction}
                     backgroundColor={returnEmptyString}
-                    selectOnLoad={false}
                     parentActive={returnFalse}
                     whenActiveChanged={returnFalse}
                     bringToFront={emptyFunction}
diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx
index 41fc49c2e..672892fdf 100644
--- a/src/client/views/search/SearchItem.tsx
+++ b/src/client/views/search/SearchItem.tsx
@@ -209,7 +209,6 @@ export class SearchItem extends React.Component<SearchItemProps> {
                     PanelHeight={returnYDimension}
                     focus={emptyFunction}
                     backgroundColor={returnEmptyString}
-                    selectOnLoad={false}
                     parentActive={returnFalse}
                     whenActiveChanged={returnFalse}
                     bringToFront={emptyFunction}
-- 
cgit v1.2.3-70-g09d2


From 0b43aead85c0de5877c0ecea7703acb6f2539249 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 29 Aug 2019 13:48:15 -0400
Subject: fixed re-opening linkbox.  adding linkbox dragging.

---
 src/client/views/OverlayView.scss          |  5 ++
 src/client/views/OverlayView.tsx           | 77 +++++++++++++++++++++---------
 src/client/views/linking/LinkFollowBox.tsx |  5 +-
 src/client/views/linking/LinkMenuItem.tsx  |  7 +--
 4 files changed, 67 insertions(+), 27 deletions(-)

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

diff --git a/src/client/views/OverlayView.scss b/src/client/views/OverlayView.scss
index dc122497f..26c2e0e1e 100644
--- a/src/client/views/OverlayView.scss
+++ b/src/client/views/OverlayView.scss
@@ -39,4 +39,9 @@
     width: 10px;
     height: 10px;
     cursor: nwse-resize;
+}
+
+.overlayView-doc {
+    z-index: 1;
+    position: absolute;
 }
\ No newline at end of file
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 8d80ad1f1..bc02a49c6 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -1,7 +1,7 @@
 import * as React from "react";
 import { observer } from "mobx-react";
 import { observable, action } from "mobx";
-import { Utils, emptyFunction, returnOne, returnTrue, returnEmptyString } from "../../Utils";
+import { Utils, emptyFunction, returnOne, returnTrue, returnEmptyString, returnZero, returnFalse } from "../../Utils";
 
 import './OverlayView.scss';
 import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils";
@@ -10,6 +10,8 @@ import { Id } from "../../new_fields/FieldSymbols";
 import { DocumentView } from "./nodes/DocumentView";
 import { Transform } from "../util/Transform";
 import { CollectionFreeFormDocumentView } from "./nodes/CollectionFreeFormDocumentView";
+import { DocumentContentsView } from "./nodes/DocumentContentsView";
+import { NumCast } from "../../new_fields/Types";
 
 export type OverlayDisposer = () => void;
 
@@ -142,27 +144,58 @@ export class OverlayView extends React.Component {
         return (
             <div className="overlayView" id="overlayView">
                 {this._elements}
-                {CurrentUserUtils.UserDocument.overlays instanceof Doc && DocListCast(CurrentUserUtils.UserDocument.overlays.data).map(d => (
-                    <CollectionFreeFormDocumentView key={d[Id]}
-                        Document={d}
-                        bringToFront={emptyFunction}
-                        addDocument={undefined}
-                        removeDocument={undefined}
-                        ContentScaling={returnOne}
-                        PanelWidth={returnOne}
-                        PanelHeight={returnOne}
-                        ScreenToLocalTransform={Transform.Identity}
-                        renderDepth={1}
-                        selectOnLoad={false}
-                        parentActive={returnTrue}
-                        whenActiveChanged={emptyFunction}
-                        focus={emptyFunction}
-                        backgroundColor={returnEmptyString}
-                        addDocTab={emptyFunction}
-                        pinToPres={emptyFunction}
-                        ContainingCollectionView={undefined}
-                        zoomToScale={emptyFunction}
-                        getScale={returnOne} />))}
+                {CurrentUserUtils.UserDocument.overlays instanceof Doc && DocListCast(CurrentUserUtils.UserDocument.overlays.data).map(d => {
+                    let offsetx = 0, offsety = 0;
+                    let onPointerMove = action((e: PointerEvent) => {
+                        if (e.buttons === 1) {
+                            d.x = e.clientX + offsetx;
+                            d.y = e.clientY + offsety;
+                            e.stopPropagation();
+                            e.preventDefault();
+                        }
+                    });
+                    let onPointerUp = action((e: PointerEvent) => {
+                        document.removeEventListener("pointermove", onPointerMove);
+                        document.removeEventListener("pointerup", onPointerUp);
+                        e.stopPropagation();
+                        e.preventDefault();
+                    });
+
+                    let onPointerDown = (e: React.PointerEvent) => {
+                        offsetx = NumCast(d.x) - e.clientX;
+                        offsety = NumCast(d.y) - e.clientY;
+                        e.stopPropagation();
+                        e.preventDefault();
+                        document.addEventListener("pointermove", onPointerMove);
+                        document.addEventListener("pointerup", onPointerUp);
+                    }
+                    return <div className="overlayView-doc" key={d[Id]} onPointerDown={onPointerDown} style={{ transform: `translate(${d.x}px, ${d.y}px)` }}>
+                        <DocumentContentsView
+                            Document={d}
+                            ChromeHeight={returnZero}
+                            isSelected={returnFalse}
+                            select={emptyFunction}
+                            layoutKey={"layout"}
+                            bringToFront={emptyFunction}
+                            addDocument={undefined}
+                            removeDocument={undefined}
+                            ContentScaling={returnOne}
+                            PanelWidth={returnOne}
+                            PanelHeight={returnOne}
+                            ScreenToLocalTransform={Transform.Identity}
+                            renderDepth={1}
+                            selectOnLoad={false}
+                            parentActive={returnTrue}
+                            whenActiveChanged={emptyFunction}
+                            focus={emptyFunction}
+                            backgroundColor={returnEmptyString}
+                            addDocTab={emptyFunction}
+                            pinToPres={emptyFunction}
+                            ContainingCollectionView={undefined}
+                            zoomToScale={emptyFunction}
+                            getScale={returnOne} />
+                    </div>
+                })}
             </div>
         );
     }
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index 54670e2c7..07f07f72a 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -38,7 +38,7 @@ enum FollowOptions {
 export class LinkFollowBox extends React.Component<FieldViewProps> {
 
     public static LayoutString() { return FieldView.LayoutString(LinkFollowBox); }
-    public static Instance: LinkFollowBox;
+    public static Instance: LinkFollowBox | undefined;
     @observable static linkDoc: Doc | undefined = undefined;
     @observable static destinationDoc: Doc | undefined = undefined;
     @observable static sourceDoc: Doc | undefined = undefined;
@@ -557,7 +557,8 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
 
     async close() {
         let res = await DocListCastAsync((CurrentUserUtils.UserDocument.overlays as Doc).data);
-        if (res) res.splice(res.indexOf(LinkFollowBox.Instance.props.Document), 1);
+        if (res) res.splice(res.indexOf(LinkFollowBox.Instance!.props.Document), 1);
+        LinkFollowBox.Instance = undefined;
     }
 
     render() {
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 0ae578d5a..6c10d4fb6 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -100,9 +100,10 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         if (LinkFollowBox.Instance === undefined) {
             let doc = await Docs.Create.LinkFollowBoxDocument({ x: MainView.Instance.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
             await Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc);
+        } else {
+            LinkFollowBox.Instance!.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
+            LinkFollowBox.Instance!.defaultLinkBehavior();
         }
-        LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
-        LinkFollowBox.Instance.defaultLinkBehavior();
     }
 
     @action.bound
@@ -113,7 +114,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         } else {
             MainView.Instance.toggleLinkFollowBox(false);
         }
-        LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
+        LinkFollowBox.Instance!.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
     }
 
     render() {
-- 
cgit v1.2.3-70-g09d2


From f6c15087d30f27c15b3b6304af58c93c65536131 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Thu, 29 Aug 2019 14:50:22 -0400
Subject: changed linkFollowBox creation approach.  fixed target contexts to
 add link default.

---
 src/client/views/MainView.tsx                      |   8 +-
 src/client/views/OverlayView.tsx                   | 108 +++++++++++----------
 src/client/views/linking/LinkFollowBox.tsx         |  20 ++--
 src/client/views/linking/LinkMenuItem.tsx          |  18 ++--
 .../views/nodes/CollectionFreeFormDocumentView.tsx |   1 -
 src/client/views/nodes/FormattedTextBoxComment.tsx |   8 +-
 .../authentication/models/current_user_utils.ts    |   3 +
 7 files changed, 78 insertions(+), 88 deletions(-)

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

diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 1fc8d1397..b64986084 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -438,13 +438,7 @@ export class MainView extends React.Component {
         if (LinkFollowBox.Instance) {
             let dvs = DocumentManager.Instance.getDocumentViews(LinkFollowBox.Instance.props.Document);
             // if it already exisits, close it
-            if (dvs.length > 0 && shouldClose) LinkFollowBox.Instance.close();
-            // open it if not
-            else Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", LinkFollowBox.Instance.props.Document);
-        }
-        else {
-            let doc = Docs.Create.LinkFollowBoxDocument({ x: this.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
-            Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc);
+            LinkFollowBox.Instance.props.Document.isMinimized = (dvs.length > 0 && shouldClose);
         }
     }
 
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index a1afe651c..54ab8696e 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -1,6 +1,6 @@
 import * as React from "react";
 import { observer } from "mobx-react";
-import { observable, action } from "mobx";
+import { observable, action, trace, computed } from "mobx";
 import { Utils, emptyFunction, returnOne, returnTrue, returnEmptyString, returnZero, returnFalse } from "../../Utils";
 
 import './OverlayView.scss';
@@ -140,61 +140,65 @@ export class OverlayView extends React.Component {
         return remove;
     }
 
+    @computed get overlayDocs() {
+        return CurrentUserUtils.UserDocument.overlays instanceof Doc && DocListCast(CurrentUserUtils.UserDocument.overlays.data).map(d => {
+            let offsetx = 0, offsety = 0;
+            let onPointerMove = action((e: PointerEvent) => {
+                if (e.buttons === 1) {
+                    d.x = e.clientX + offsetx;
+                    d.y = e.clientY + offsety;
+                    e.stopPropagation();
+                    e.preventDefault();
+                }
+            });
+            let onPointerUp = action((e: PointerEvent) => {
+                document.removeEventListener("pointermove", onPointerMove);
+                document.removeEventListener("pointerup", onPointerUp);
+                e.stopPropagation();
+                e.preventDefault();
+            });
+
+            let onPointerDown = (e: React.PointerEvent) => {
+                offsetx = NumCast(d.x) - e.clientX;
+                offsety = NumCast(d.y) - e.clientY;
+                e.stopPropagation();
+                e.preventDefault();
+                document.addEventListener("pointermove", onPointerMove);
+                document.addEventListener("pointerup", onPointerUp);
+            };
+            return <div className="overlayView-doc" key={d[Id]} onPointerDown={onPointerDown} style={{ transform: `translate(${d.x}px, ${d.y}px)`, display: d.isMinimized ? "none" : "" }}>
+                <DocumentContentsView
+                    Document={d}
+                    ChromeHeight={returnZero}
+                    isSelected={returnFalse}
+                    select={emptyFunction}
+                    layoutKey={"layout"}
+                    bringToFront={emptyFunction}
+                    addDocument={undefined}
+                    removeDocument={undefined}
+                    ContentScaling={returnOne}
+                    PanelWidth={returnOne}
+                    PanelHeight={returnOne}
+                    ScreenToLocalTransform={Transform.Identity}
+                    renderDepth={1}
+                    parentActive={returnTrue}
+                    whenActiveChanged={emptyFunction}
+                    focus={emptyFunction}
+                    backgroundColor={returnEmptyString}
+                    addDocTab={emptyFunction}
+                    pinToPres={emptyFunction}
+                    ContainingCollectionView={undefined}
+                    zoomToScale={emptyFunction}
+                    getScale={returnOne} />
+            </div>;
+        })
+    }
+
     render() {
         return (
             <div className="overlayView" id="overlayView">
                 {this._elements}
-                {CurrentUserUtils.UserDocument.overlays instanceof Doc && DocListCast(CurrentUserUtils.UserDocument.overlays.data).map(d => {
-                    let offsetx = 0, offsety = 0;
-                    let onPointerMove = action((e: PointerEvent) => {
-                        if (e.buttons === 1) {
-                            d.x = e.clientX + offsetx;
-                            d.y = e.clientY + offsety;
-                            e.stopPropagation();
-                            e.preventDefault();
-                        }
-                    });
-                    let onPointerUp = action((e: PointerEvent) => {
-                        document.removeEventListener("pointermove", onPointerMove);
-                        document.removeEventListener("pointerup", onPointerUp);
-                        e.stopPropagation();
-                        e.preventDefault();
-                    });
-
-                    let onPointerDown = (e: React.PointerEvent) => {
-                        offsetx = NumCast(d.x) - e.clientX;
-                        offsety = NumCast(d.y) - e.clientY;
-                        e.stopPropagation();
-                        e.preventDefault();
-                        document.addEventListener("pointermove", onPointerMove);
-                        document.addEventListener("pointerup", onPointerUp);
-                    }
-                    return <div className="overlayView-doc" key={d[Id]} onPointerDown={onPointerDown} style={{ transform: `translate(${d.x}px, ${d.y}px)` }}>
-                        <DocumentContentsView
-                            Document={d}
-                            ChromeHeight={returnZero}
-                            isSelected={returnFalse}
-                            select={emptyFunction}
-                            layoutKey={"layout"}
-                            bringToFront={emptyFunction}
-                            addDocument={undefined}
-                            removeDocument={undefined}
-                            ContentScaling={returnOne}
-                            PanelWidth={returnOne}
-                            PanelHeight={returnOne}
-                            ScreenToLocalTransform={Transform.Identity}
-                            renderDepth={1}
-                            parentActive={returnTrue}
-                            whenActiveChanged={emptyFunction}
-                            focus={emptyFunction}
-                            backgroundColor={returnEmptyString}
-                            addDocTab={emptyFunction}
-                            pinToPres={emptyFunction}
-                            ContainingCollectionView={undefined}
-                            zoomToScale={emptyFunction}
-                            getScale={returnOne} />
-                    </div>
-                })}
+                {this.overlayDocs}
             </div>
         );
     }
diff --git a/src/client/views/linking/LinkFollowBox.tsx b/src/client/views/linking/LinkFollowBox.tsx
index 07f07f72a..74663f9af 100644
--- a/src/client/views/linking/LinkFollowBox.tsx
+++ b/src/client/views/linking/LinkFollowBox.tsx
@@ -1,4 +1,4 @@
-import { observable, computed, action, trace, ObservableMap, runInAction, reaction, IReactionDisposer } from "mobx";
+import { observable, computed, action, runInAction, reaction, IReactionDisposer } from "mobx";
 import React = require("react");
 import { observer } from "mobx-react";
 import { FieldViewProps, FieldView } from "../nodes/FieldView";
@@ -15,8 +15,6 @@ import { SearchUtil } from "../../util/SearchUtil";
 import { Id } from "../../../new_fields/FieldSymbols";
 import { listSpec } from "../../../new_fields/Schema";
 import { DocServer } from "../../DocServer";
-import { RefField } from "../../../new_fields/RefField";
-import { Docs } from "../../documents/Documents";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { faTimes } from '@fortawesome/free-solid-svg-icons';
 import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
@@ -126,9 +124,11 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
             const allDocs = await Promise.all(aliases.map(doc => SearchUtil.Search("", true, { fq: `data_l:"${doc[Id]}"` }).then(result => result.docs)));
             allDocs.forEach((docs, index) => docs.forEach(doc => map.set(doc, aliases[index])));
             docs.forEach(doc => map.delete(doc));
-            runInAction(() => {
+            runInAction(async () => {
                 this._docs = docs.filter(doc => !Doc.AreProtosEqual(doc, CollectionDockingView.Instance.props.Document)).map(doc => ({ col: doc, target: dest }));
                 this._otherDocs = Array.from(map.entries()).filter(entry => !Doc.AreProtosEqual(entry[0], CollectionDockingView.Instance.props.Document)).map(([col, target]) => ({ col, target }));
+                let tcontext = LinkFollowBox.linkDoc && (await Cast(LinkFollowBox.linkDoc.targetContext, Doc)) as Doc;
+                runInAction(() => tcontext && this._docs.splice(0, 0, { col: tcontext, target: dest }));
             });
         }
     }
@@ -268,7 +268,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
             let fullScreenAlias = Doc.MakeAlias(LinkFollowBox.destinationDoc);
             // THIS IS EMPTY FUNCTION
             this.props.addDocTab(fullScreenAlias, undefined, "inTab");
-            console.log(this.props.addDocTab)
+            console.log(this.props.addDocTab);
 
             this.highlightDoc();
             SelectionManager.DeselectAll();
@@ -348,7 +348,7 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
             }
             else if (this.selectedMode === FollowModes.OPENTAB) {
                 if (notOpenInContext) this.openLinkTab();
-                else this.selectedContext && this.openLinkColTab({ context: this.selectedContext, shouldZoom: shouldZoom })
+                else this.selectedContext && this.openLinkColTab({ context: this.selectedContext, shouldZoom: shouldZoom });
             }
             else if (this.selectedMode === FollowModes.PAN) {
                 this.jumpToLink({ shouldZoom: shouldZoom });
@@ -555,19 +555,13 @@ export class LinkFollowBox extends React.Component<FieldViewProps> {
         return null;
     }
 
-    async close() {
-        let res = await DocListCastAsync((CurrentUserUtils.UserDocument.overlays as Doc).data);
-        if (res) res.splice(res.indexOf(LinkFollowBox.Instance!.props.Document), 1);
-        LinkFollowBox.Instance = undefined;
-    }
-
     render() {
         return (
             <div className="linkFollowBox-main" style={{ height: NumCast(this.props.Document.height), width: NumCast(this.props.Document.width) }}>
                 <div className="linkFollowBox-header">
                     <div className="topHeader">
                         {LinkFollowBox.linkDoc ? "Link Title: " + StrCast(LinkFollowBox.linkDoc.title) : "No Link Selected"}
-                        <div onClick={this.close} className="closeDocument"><FontAwesomeIcon icon={faTimes} size="lg" /></div>
+                        <div onClick={() => this.props.Document.isMinimized = true} className="closeDocument"><FontAwesomeIcon icon={faTimes} size="lg" /></div>
                     </div>
                     <div className=" direction-indicator">{LinkFollowBox.linkDoc ?
                         LinkFollowBox.sourceDoc && LinkFollowBox.destinationDoc ? "Source: " + StrCast(LinkFollowBox.sourceDoc.title) + ", Destination: " + StrCast(LinkFollowBox.destinationDoc.title)
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 6c10d4fb6..780f161d3 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -97,24 +97,20 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
 
     @action.bound
     async followDefault() {
-        if (LinkFollowBox.Instance === undefined) {
-            let doc = await Docs.Create.LinkFollowBoxDocument({ x: MainView.Instance.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
-            await Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc);
-        } else {
-            LinkFollowBox.Instance!.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
-            LinkFollowBox.Instance!.defaultLinkBehavior();
+        if (LinkFollowBox.Instance !== undefined) {
+            LinkFollowBox.Instance.props.Document.isMinimized = false;
+            LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
+            LinkFollowBox.Instance.defaultLinkBehavior();
         }
     }
 
     @action.bound
     async openLinkFollower() {
-        if (LinkFollowBox.Instance === undefined) {
-            let doc = await Docs.Create.LinkFollowBoxDocument({ x: MainView.Instance.flyoutWidth, y: 20, width: 500, height: 370, title: "Link Follower" });
-            await Doc.AddDocToList(Cast(CurrentUserUtils.UserDocument.overlays, Doc) as Doc, "data", doc);
-        } else {
+        if (LinkFollowBox.Instance !== undefined) {
+            LinkFollowBox.Instance.props.Document.isMinimized = false;
             MainView.Instance.toggleLinkFollowBox(false);
+            LinkFollowBox.Instance.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
         }
-        LinkFollowBox.Instance!.setLinkDocs(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc);
     }
 
     render() {
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 7631ecc6c..c9c394960 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -8,7 +8,6 @@ import { DocumentView, DocumentViewProps, positionSchema } from "./DocumentView"
 import "./DocumentView.scss";
 import React = require("react");
 import { Doc } from "../../../new_fields/Doc";
-import { returnEmptyString } from "../../../Utils";
 
 export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
     x?: number;
diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx
index 9123f8aed..0287d93a9 100644
--- a/src/client/views/nodes/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/FormattedTextBoxComment.tsx
@@ -1,12 +1,12 @@
-import { Plugin, EditorState } from "prosemirror-state"
-import './FormattedTextBoxComment.scss'
+import { Plugin, EditorState } from "prosemirror-state";
+import './FormattedTextBoxComment.scss';
 import { ResolvedPos, Mark } from "prosemirror-model";
 import { EditorView } from "prosemirror-view";
 import { Doc } from "../../../new_fields/Doc";
 
 export let selectionSizePlugin = new Plugin({
     view(editorView) { return new SelectionSizeTooltip(editorView); }
-})
+});
 export function findOtherUserMark(marks: Mark[]): Mark | undefined {
     return marks.find(m => m.attrs.userid && m.attrs.userid !== Doc.CurrentUserEmail);
 }
@@ -106,5 +106,5 @@ export class SelectionSizeTooltip {
         }
     }
 
-    destroy() { SelectionSizeTooltip.tooltip.style.display = "none" }
+    destroy() { SelectionSizeTooltip.tooltip.style.display = "none"; }
 }
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 83e45d3ce..9866e22eb 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -79,6 +79,9 @@ export class CurrentUserUtils {
             Doc.GetProto(overlays).backgroundColor = "#aca3a6";
             doc.overlays = overlays;
         }
+        if (doc.linkFollowBox === undefined) {
+            PromiseValue(Cast(doc.overlays, Doc)).then(overlays => overlays && Doc.AddDocToList(overlays, "data", doc.linkFollowBox = Docs.Create.LinkFollowBoxDocument({ x: 250, y: 20, width: 500, height: 370, title: "Link Follower" })));
+        }
         StrCast(doc.title).indexOf("@") !== -1 && (doc.title = StrCast(doc.title).split("@")[0] + "'s Library");
         doc.width = 100;
         doc.preventTreeViewOpen = true;
-- 
cgit v1.2.3-70-g09d2


From 2262d7562b57c37c238fc8a7c373304984a5fe3b Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 4 Sep 2019 17:49:19 -0400
Subject: prosemirror restructuring.

---
 src/client/util/ProsemirrorExampleTransfer.ts      | 71 +++++-----------------
 src/client/util/RichTextSchema.tsx                 | 71 +++++++++++-----------
 src/client/util/TooltipTextMenu.tsx                | 37 ++++++-----
 src/client/util/prosemirrorPatches.js              | 30 +++++++++
 src/client/views/OverlayView.tsx                   |  2 +-
 src/client/views/nodes/FormattedTextBox.tsx        |  6 +-
 src/client/views/nodes/FormattedTextBoxComment.tsx |  4 +-
 src/client/views/pdf/Page.tsx                      |  2 +-
 8 files changed, 107 insertions(+), 116 deletions(-)

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

diff --git a/src/client/util/ProsemirrorExampleTransfer.ts b/src/client/util/ProsemirrorExampleTransfer.ts
index 5016e72c6..9c4b2d3d1 100644
--- a/src/client/util/ProsemirrorExampleTransfer.ts
+++ b/src/client/util/ProsemirrorExampleTransfer.ts
@@ -2,8 +2,8 @@ import { chainCommands, exitCode, joinDown, joinUp, lift, selectParentNode, setB
 import { redo, undo } from "prosemirror-history";
 import { undoInputRule } from "prosemirror-inputrules";
 import { Schema } from "prosemirror-model";
-import { liftListItem, } from "./prosemirrorPatches.js";
-import { splitListItem, wrapInList, sinkListItem } from "prosemirror-schema-list";
+import { liftListItem, sinkListItem } from "./prosemirrorPatches.js";
+import { splitListItem, wrapInList, } from "prosemirror-schema-list";
 import { EditorState, Transaction, TextSelection, NodeSelection } from "prosemirror-state";
 import { TooltipTextMenu } from "./TooltipTextMenu";
 
@@ -62,7 +62,7 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
             return true;
         }
         return false;
-    })
+    });
 
 
     let cmd = chainCommands(exitCode, (state, dispatch) => {
@@ -93,54 +93,16 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
 
     bind("Mod-s", TooltipTextMenu.insertStar);
 
-    let updateOrderedList = (start: number, rangeStart: any, delta: number, tx2: Transaction, forward: boolean) => {
-        let bs = rangeStart.attrs.bulletStyle;
-        bs + delta > 0 && tx2.setNodeMarkup(start, rangeStart.type, { mapStyle: rangeStart.attrs.mapStyle, bulletStyle: rangeStart.attrs.bulletStyle + delta }, rangeStart.marks);
-
-        let brk = false;
-        rangeStart.descendants((node: any, offset: any, index: any) => {
+    let updateBullets = (tx2: Transaction) => {
+        tx2.doc.descendants((node: any, offset: any, index: any) => {
             if (node.type === schema.nodes.ordered_list || node.type === schema.nodes.list_item) {
-                if (!brk && (bs !== node.attrs.bulletStyle || delta > 0 || (forward && bs > 1))) {
-                    tx2.setNodeMarkup(start + offset + 1, node.type, { mapStyle: node.attrs.mapStyle, bulletStyle: node.attrs.bulletStyle + delta }, node.marks);
-                } else {
-                    brk = true;
-                }
+                let path = (tx2.doc.resolve(offset) as any).path;
+                let depth = Array.from(path).reduce((p: number, c: any) => p + (c.hasOwnProperty("type") && (c as any).type === schema.nodes.ordered_list ? 1 : 0), 0);
+                if (node.type === schema.nodes.ordered_list) depth++;
+                tx2.setNodeMarkup(offset, node.type, { mapStyle: node.attrs.mapStyle, bulletStyle: depth }, node.marks);
             }
         });
-    }
-
-    let updateBullets = (tx2: Transaction, refStart: number, delta: number) => {
-        let i = refStart;
-        for (let i = refStart; i >= 0; i--) {
-            let testPos = tx2.doc.nodeAt(i);
-            if (!testPos) {
-                for (let i = refStart + 1; i <= tx2.doc.nodeSize; i++) {
-                    try {
-                        let testPos = tx2.doc.nodeAt(i);
-                        if (testPos && testPos.type === schema.nodes.ordered_list) {
-                            updateOrderedList(i, testPos, delta, tx2, true);
-                            break;
-                        }
-                    } catch (e) {
-                        break;
-                    }
-                }
-                break;
-            }
-            if ((testPos.type === schema.nodes.list_item || testPos.type === schema.nodes.ordered_list)) {
-                let start = i;
-                let preve = i > 0 && tx2.doc.nodeAt(start - 1);
-                if (preve && preve.type === schema.nodes.ordered_list) {
-                    start = start - 1;
-                }
-                let rangeStart = tx2.doc.nodeAt(start);
-                if (rangeStart) {
-                    updateOrderedList(start, rangeStart, delta, tx2, false);
-                }
-                break;
-            }
-        }
-    }
+    };
 
 
     bind("Tab", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
@@ -148,8 +110,7 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
         var range = ref.$from.blockRange(ref.$to);
         var marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
         if (!sinkListItem(schema.nodes.list_item)(state, (tx2: Transaction) => {
-            var range = state.selection.$from.blockRange(state.selection.$to);
-            updateBullets(tx2, range!.start - 1, 1);
+            updateBullets(tx2);
             marks && tx2.ensureMarks([...marks]);
             marks && tx2.setStoredMarks([...marks]);
             dispatch(tx2);
@@ -157,7 +118,7 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
             let sxf = state.tr.setSelection(TextSelection.create(state.doc, range!.start, range!.end));
             let newstate = state.applyTransaction(sxf);
             if (!wrapInList(schema.nodes.ordered_list)(newstate.state, (tx2: Transaction) => {
-                updateBullets(tx2, range!.start, 1);
+                updateBullets(tx2);
                 // when promoting to a list, assume list will format things so don't copy the stored marks.
                 marks && tx2.ensureMarks([...marks]);
                 marks && tx2.setStoredMarks([...marks]);
@@ -169,14 +130,10 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?:
     });
 
     bind("Shift-Tab", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
-        var range = state.selection.$from.blockRange(state.selection.$to);
         var marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks());
 
-        let tr = state.tr;
-
-        if (!liftListItem(schema.nodes.list_item)(tr, (tx2: Transaction) => {
-            var range = tx2.selection.$from.blockRange(tx2.selection.$to);
-            updateBullets(tx2, range!.start, -1);
+        if (!liftListItem(schema.nodes.list_item)(state.tr, (tx2: Transaction) => {
+            updateBullets(tx2);
             marks && tx2.ensureMarks([...marks]);
             marks && tx2.setStoredMarks([...marks]);
             dispatch(tx2);
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index 75e982872..3174d668c 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -597,8 +597,6 @@ export class ImageResizeView {
 }
 
 export class OrderedListView {
-    constructor(node: any, view: any, getPos: any) { }
-
     update(node: any) {
         return false; // if attr's of an ordered_list (e.g., bulletStyle) change, return false forces the dom node to be recreated which is necessary for the bullet labels to update
     }
@@ -613,33 +611,33 @@ export class FootnoteView {
 
     constructor(node: any, view: any, getPos: any) {
         // We'll need these later
-        this.node = node
-        this.outerView = view
-        this.getPos = getPos
+        this.node = node;
+        this.outerView = view;
+        this.getPos = getPos;
 
         // The node's representation in the editor (empty, for now)
         this.dom = document.createElement("footnote");
         this.dom.addEventListener("pointerup", this.toggle, true);
         // These are used when the footnote is selected
-        this.innerView = null
+        this.innerView = null;
     }
     selectNode() {
         const attrs = { ...this.node.attrs };
         attrs.visibility = true;
-        this.dom.classList.add("ProseMirror-selectednode")
-        if (!this.innerView) this.open()
+        this.dom.classList.add("ProseMirror-selectednode");
+        if (!this.innerView) this.open();
     }
 
     deselectNode() {
         const attrs = { ...this.node.attrs };
         attrs.visibility = false;
-        this.dom.classList.remove("ProseMirror-selectednode")
-        if (this.innerView) this.close()
+        this.dom.classList.remove("ProseMirror-selectednode");
+        if (this.innerView) this.close();
     }
     open() {
-        if (!(this.outerView as any).isOverlay) return;
+        if (!this.outerView.isOverlay) return;
         // Append a tooltip to the outer node
-        let tooltip = this.dom.appendChild(document.createElement("div"))
+        let tooltip = this.dom.appendChild(document.createElement("div"));
         tooltip.className = "footnote-tooltip";
         // And put a sub-ProseMirror into that
         this.innerView = new EditorView(tooltip, {
@@ -679,56 +677,55 @@ export class FootnoteView {
         if (this.innerView) this.close();
         else {
             this.open();
-
         }
     }
     close() {
-        this.innerView && this.innerView.destroy()
-        this.innerView = null
-        this.dom.textContent = ""
+        this.innerView && this.innerView.destroy();
+        this.innerView = null;
+        this.dom.textContent = "";
     }
     dispatchInner(tr: any) {
-        let { state, transactions } = this.innerView.state.applyTransaction(tr)
-        this.innerView.updateState(state)
+        let { state, transactions } = this.innerView.state.applyTransaction(tr);
+        this.innerView.updateState(state);
 
         if (!tr.getMeta("fromOutside")) {
-            let outerTr = this.outerView.state.tr, offsetMap = StepMap.offset(this.getPos() + 1)
-            for (let i = 0; i < transactions.length; i++) {
-                let steps = transactions[i].steps
-                for (let j = 0; j < steps.length; j++)
-                    outerTr.step(steps[j].map(offsetMap))
+            let outerTr = this.outerView.state.tr, offsetMap = StepMap.offset(this.getPos() + 1);
+            for (let steps of transactions) {
+                for (let step of steps) {
+                    outerTr.step(step.map(offsetMap));
+                }
             }
-            if (outerTr.docChanged) this.outerView.dispatch(outerTr)
+            if (outerTr.docChanged) this.outerView.dispatch(outerTr);
         }
     }
     update(node: any) {
-        if (!node.sameMarkup(this.node)) return false
-        this.node = node
+        if (!node.sameMarkup(this.node)) return false;
+        this.node = node;
         if (this.innerView) {
-            let state = this.innerView.state
-            let start = node.content.findDiffStart(state.doc.content)
-            if (start != null) {
-                let { a: endA, b: endB } = node.content.findDiffEnd(state.doc.content)
-                let overlap = start - Math.min(endA, endB)
-                if (overlap > 0) { endA += overlap; endB += overlap }
+            let state = this.innerView.state;
+            let start = node.content.findDiffStart(state.doc.content);
+            if (start !== null) {
+                let { a: endA, b: endB } = node.content.findDiffEnd(state.doc.content);
+                let overlap = start - Math.min(endA, endB);
+                if (overlap > 0) { endA += overlap; endB += overlap; }
                 this.innerView.dispatch(
                     state.tr
                         .replace(start, endB, node.slice(start, endA))
-                        .setMeta("fromOutside", true))
+                        .setMeta("fromOutside", true));
             }
         }
-        return true
+        return true;
     }
 
     destroy() {
-        if (this.innerView) this.close()
+        if (this.innerView) this.close();
     }
 
     stopEvent(event: any) {
-        return this.innerView && this.innerView.dom.contains(event.target)
+        return this.innerView && this.innerView.dom.contains(event.target);
     }
 
-    ignoreMutation() { return true }
+    ignoreMutation() { return true; }
 }
 
 export class SummarizedView {
diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx
index ce7b04e31..6d375fc1d 100644
--- a/src/client/util/TooltipTextMenu.tsx
+++ b/src/client/util/TooltipTextMenu.tsx
@@ -4,7 +4,7 @@ import { action, observable } from "mobx";
 import { Dropdown, icons, MenuItem } from "prosemirror-menu"; //no import css
 import { Mark, MarkType, Node as ProsNode, NodeType, ResolvedPos, Schema } from "prosemirror-model";
 import { wrapInList } from 'prosemirror-schema-list';
-import { EditorState, NodeSelection, TextSelection } from "prosemirror-state";
+import { EditorState, NodeSelection, TextSelection, Transaction } from "prosemirror-state";
 import { EditorView } from "prosemirror-view";
 import { Doc, Field, Opt } from "../../new_fields/Doc";
 import { Id } from "../../new_fields/FieldSymbols";
@@ -509,30 +509,37 @@ export class TooltipTextMenu {
         }
     }
 
+    updateBullets = (tx2: Transaction, style: string) => {
+        tx2.doc.descendants((node: any, offset: any, index: any) => {
+            if (node.type === schema.nodes.ordered_list || node.type === schema.nodes.list_item) {
+                let path = (tx2.doc.resolve(offset) as any).path;
+                let depth = Array.from(path).reduce((p: number, c: any) => p + (c.hasOwnProperty("type") && (c as any).type === schema.nodes.ordered_list ? 1 : 0), 0);
+                if (node.type === schema.nodes.ordered_list) depth++;
+                tx2.setNodeMarkup(offset, node.type, { mapStyle: style, bulletStyle: depth }, node.marks);
+            }
+        });
+    };
     //remove all node typeand apply the passed-in one to the selected text
-    changeToNodeType(nodeType: NodeType | undefined, view: EditorView) {
+    changeToNodeType = (nodeType: NodeType | undefined, view: EditorView) => {
         //remove oldif (nodeType) { //add new
         if (nodeType === schema.nodes.bullet_list) {
             wrapInList(nodeType)(view.state, view.dispatch);
         } else {
-            var ref = view.state.selection;
-            var range = ref.$from.blockRange(ref.$to);
             var marks = view.state.storedMarks || (view.state.selection.$to.parentOffset && view.state.selection.$from.marks());
-            wrapInList(schema.nodes.ordered_list)(view.state, (tx2: any) => {
-                const resolvedPos = tx2.doc.resolve(Math.round((range!.start + range!.end) / 2));
-                let path = resolvedPos.path;
-                for (let i = path.length - 1; i > 0; i--) {
-                    if (path[i].type === schema.nodes.ordered_list) {
-                        path[i].attrs.bulletStyle = 1;
-                        path[i].attrs.mapStyle = (nodeType as any).attrs.mapStyle;
-                        break;
-                    }
-                }
+            if (!wrapInList(schema.nodes.ordered_list)(view.state, (tx2: any) => {
+                this.updateBullets(tx2, (nodeType as any).attrs.mapStyle);
                 marks && tx2.ensureMarks([...marks]);
                 marks && tx2.setStoredMarks([...marks]);
 
                 view.dispatch(tx2);
-            });
+            })) {
+                let tx2 = view.state.tr;
+                this.updateBullets(tx2, (nodeType as any).attrs.mapStyle);
+                marks && tx2.ensureMarks([...marks]);
+                marks && tx2.setStoredMarks([...marks]);
+
+                view.dispatch(tx2);
+            }
         }
     }
 
diff --git a/src/client/util/prosemirrorPatches.js b/src/client/util/prosemirrorPatches.js
index c273c2323..6bf4395ad 100644
--- a/src/client/util/prosemirrorPatches.js
+++ b/src/client/util/prosemirrorPatches.js
@@ -6,6 +6,7 @@ var prosemirrorTransform = require('prosemirror-transform');
 var prosemirrorModel = require('prosemirror-model');
 
 exports.liftListItem = liftListItem;
+exports.sinkListItem = sinkListItem;
 // :: (NodeType) → (state: EditorState, dispatch: ?(tr: Transaction)) → bool
 // Create a command to lift the list item around the selection up into
 // a wrapping list.
@@ -59,4 +60,33 @@ function liftOutOfList(tr, dispatch, range) {
             atStart ? 0 : 1, atEnd ? 0 : 1), atStart ? 0 : 1));
     dispatch(tr.scrollIntoView());
     return true
+}
+
+// :: (NodeType) → (state: EditorState, dispatch: ?(tr: Transaction)) → bool
+// Create a command to sink the list item around the selection down
+// into an inner list.
+function sinkListItem(itemType) {
+    return function (state, dispatch) {
+        var ref = state.selection;
+        var $from = ref.$from;
+        var $to = ref.$to;
+        var range = $from.blockRange($to, function (node) { return node.childCount && node.firstChild.type == itemType; });
+        if (!range) { return false }
+        var startIndex = range.startIndex;
+        if (startIndex == 0) { return false }
+        var parent = range.parent, nodeBefore = parent.child(startIndex - 1);
+        if (nodeBefore.type != itemType) { return false; }
+
+        if (dispatch) {
+            var nestedBefore = nodeBefore.lastChild && nodeBefore.lastChild.type == parent.type;
+            var inner = prosemirrorModel.Fragment.from(nestedBefore ? itemType.create() : null);
+            let slice = new prosemirrorModel.Slice(prosemirrorModel.Fragment.from(itemType.create(null, prosemirrorModel.Fragment.from(parent.type.create(parent.attrs, inner)))),
+                nestedBefore ? 3 : 1, 0);
+            var before = range.start, after = range.end;
+            dispatch(state.tr.step(new prosemirrorTransform.ReplaceAroundStep(before - (nestedBefore ? 3 : 1), after,
+                before, after, slice, 1, true))
+                .scrollIntoView());
+        }
+        return true
+    }
 }
\ No newline at end of file
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 54ab8696e..fe06e4440 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -191,7 +191,7 @@ export class OverlayView extends React.Component {
                     zoomToScale={emptyFunction}
                     getScale={returnOne} />
             </div>;
-        })
+        });
     }
 
     render() {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 4cb52ec78..f9ad040a2 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -174,7 +174,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
     syncNodeSelection(view: any, sel: any) {
         if (sel instanceof NodeSelection) {
             var desc = view.docView.descAt(sel.from);
-            if (desc != view.lastSelectedViewDesc) {
+            if (desc !== view.lastSelectedViewDesc) {
                 if (view.lastSelectedViewDesc) {
                     view.lastSelectedViewDesc.deselectNode();
                     view.lastSelectedViewDesc = null;
@@ -635,8 +635,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
                 nodeViews: {
                     image(node, view, getPos) { return new ImageResizeView(node, view, getPos); },
                     star(node, view, getPos) { return new SummarizedView(node, view, getPos); },
-                    ordered_list(node, view, getPos) { return new OrderedListView(node, view, getPos); },
-                    footnote(node, view, getPos) { return new FootnoteView(node, view, getPos) }
+                    ordered_list(node, view, getPos) { return new OrderedListView(); },
+                    footnote(node, view, getPos) { return new FootnoteView(node, view, getPos); }
                 },
                 clipboardTextSerializer: this.clipboardTextSerializer,
                 handlePaste: this.handlePaste,
diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx
index 255000936..2d2fff06d 100644
--- a/src/client/views/nodes/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/FormattedTextBoxComment.tsx
@@ -92,7 +92,7 @@ export class FormattedTextBoxComment {
         if (lastState && lastState.doc.eq(state.doc) &&
             lastState.selection.eq(state.selection)) return;
 
-        let set = "none"
+        let set = "none";
         if (state.selection.$from) {
             let nbef = findStartOfMark(state.selection.$from, view, findOtherUserMark);
             let naft = findEndOfMark(state.selection.$from, view, findOtherUserMark);
@@ -130,7 +130,7 @@ export class FormattedTextBoxComment {
                 if (mark.attrs.href.indexOf(Utils.prepend("/doc/")) === 0) {
                     let docTarget = mark.attrs.href.replace(Utils.prepend("/doc/"), "").split("?")[0];
                     docTarget && DocServer.GetRefField(docTarget).then(linkDoc =>
-                        (linkDoc as Doc) && (FormattedTextBoxComment.tooltipText.textContent = "link :" + StrCast((linkDoc as Doc)!.title)));
+                        (linkDoc as Doc) && (FormattedTextBoxComment.tooltipText.textContent = "link :" + StrCast((linkDoc as Doc).title)));
                 }
                 // These are in screen coordinates
                 // let start = view.coordsAtPos(state.selection.from), end = view.coordsAtPos(state.selection.to);
diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx
index 8df2dce29..856e883e7 100644
--- a/src/client/views/pdf/Page.tsx
+++ b/src/client/views/pdf/Page.tsx
@@ -64,7 +64,7 @@ export default class Page extends React.Component<IPageProps> {
         // lower scale = easier to read at small sizes, higher scale = easier to read at large sizes
         if (this._state !== "rendering" && !this._page && this._canvas.current && this._textLayer.current) {
             this._state = "rendering";
-            let viewport = page.getViewport({ scale: scale });
+            let viewport = page.getViewport(scale);
             this._canvas.current.width = this._width = viewport.width;
             this._canvas.current.height = this._height = viewport.height;
             this.props.pageLoaded(viewport);
-- 
cgit v1.2.3-70-g09d2


From 3865ccd688015d92c8c551bf78ee2a9b6ece5500 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 9 Sep 2019 15:40:49 -0400
Subject: added local overlay for free form views.   added start of minimap.

---
 src/client/views/OverlayView.tsx                   |  4 +++-
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 16 ++++++++++++---
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 23 ++++++++++++++++++----
 src/client/views/nodes/DocumentView.tsx            |  2 --
 src/server/index.ts                                |  2 +-
 5 files changed, 36 insertions(+), 11 deletions(-)

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

diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index fe06e4440..da4b71e5c 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -197,7 +197,9 @@ export class OverlayView extends React.Component {
     render() {
         return (
             <div className="overlayView" id="overlayView">
-                {this._elements}
+                <div>
+                    {this._elements}
+                </div>
                 {this.overlayDocs}
             </div>
         );
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 2df2a3464..2ec2b0671 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -3,7 +3,7 @@ import { faEye } from "@fortawesome/free-regular-svg-icons";
 import { faBraille, faChalkboard, faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faPaintBrush, faTable, faUpload } from "@fortawesome/free-solid-svg-icons";
 import { action, computed, IReactionDisposer, observable, reaction, trace } from "mobx";
 import { observer } from "mobx-react";
-import { Doc, DocListCastAsync, Field, FieldResult, HeightSym, Opt, WidthSym } from "../../../../new_fields/Doc";
+import { Doc, DocListCastAsync, Field, FieldResult, HeightSym, Opt, WidthSym, DocListCast } from "../../../../new_fields/Doc";
 import { Id } from "../../../../new_fields/FieldSymbols";
 import { InkField, StrokeData } from "../../../../new_fields/InkField";
 import { createSchema, makeInterface } from "../../../../new_fields/Schema";
@@ -225,8 +225,12 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         return bounds;
     }
 
+    @computed get actualContentBounds() {
+        return this.fitToBox && !this.isAnnotationOverlay ? this.ComputeContentBounds(this.elements.filter(e => e.bounds && !e.bounds.z).map(e => e.bounds!)) : undefined;
+    }
+
     @computed get contentBounds() {
-        let bounds = this.fitToBox && !this.isAnnotationOverlay ? this.ComputeContentBounds(this.elements.filter(e => e.bounds && !e.bounds.z).map(e => e.bounds!)) : undefined;
+        let bounds = this.actualContentBounds;
         let res = {
             panX: bounds ? (bounds.x + bounds.r) / 2 : this.Document.panX || 0,
             panY: bounds ? (bounds.y + bounds.b) / 2 : this.Document.panY || 0,
@@ -775,7 +779,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
         const initScript = this.Document.arrangeInit;
         const script = this.Document.arrangeScript;
         let state: any = undefined;
-        const docs = this.childDocs;
+        let docs = this.childDocs;
+        let overlayDocs = DocListCast(this.props.Document.localOverlays);
+        overlayDocs && docs.push(...overlayDocs);
         let elements: ViewDefResult[] = [];
         if (initScript) {
             const initResult = initScript.script.run({ docs, collection: this.Document });
@@ -967,6 +973,10 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
     }
 
     render() {
+        this.props.Document.fitX = this.actualContentBounds && this.actualContentBounds.x;
+        this.props.Document.fitY = this.actualContentBounds && this.actualContentBounds.y;
+        this.props.Document.fitW = this.actualContentBounds && (this.actualContentBounds.r - this.actualContentBounds.x);
+        this.props.Document.fitH = this.actualContentBounds && (this.actualContentBounds.b - this.actualContentBounds.y);
         const easing = () => this.props.Document.panTransformType === "Ease";
         Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey);
         return (
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index f07584b4f..c059ff50d 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,7 +1,7 @@
 import { computed } from "mobx";
 import { observer } from "mobx-react";
 import { createSchema, makeInterface } from "../../../new_fields/Schema";
-import { BoolCast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types";
+import { BoolCast, FieldValue, NumCast, StrCast, Cast } from "../../../new_fields/Types";
 import { Transform } from "../../util/Transform";
 import { DocComponent } from "../DocComponent";
 import { DocumentView, DocumentViewProps, positionSchema } from "./DocumentView";
@@ -77,6 +77,21 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     clusterColorFunc = (doc: Doc) => this.clusterColor;
 
     render() {
+        let txf = this.transform;
+        let w = this.width;
+        let h = this.height;
+        let renderScript = this.Document.renderScript;
+        if (renderScript) {
+            let someView = Cast(this.Document.someView, Doc);
+            let minimap = Cast(this.Document.minimap, Doc);
+            if (someView instanceof Doc && minimap instanceof Doc) {
+                let x = (NumCast(someView.panX) - NumCast(someView.width) / 2 / NumCast(someView.scale) - (NumCast(minimap.fitX) - NumCast(minimap.fitW) / 2)) / NumCast(minimap.fitW) * NumCast(minimap.width) - NumCast(minimap.width) / 2;
+                let y = (NumCast(someView.panY) - NumCast(someView.height) / 2 / NumCast(someView.scale) - (NumCast(minimap.fitY) - NumCast(minimap.fitH) / 2)) / NumCast(minimap.fitH) * NumCast(minimap.height) - NumCast(minimap.height) / 2;
+                w = NumCast(someView.width) / NumCast(someView.scale) / NumCast(minimap.fitW) * NumCast(minimap.width);
+                h = NumCast(someView.height) / NumCast(someView.scale) / NumCast(minimap.fitH) * NumCast(minimap.height);
+                txf = `translate(${x}px,${y}px)`;
+            }
+        }
         const hasPosition = this.props.x !== undefined || this.props.y !== undefined;
         return (
             <div className="collectionFreeFormDocumentView-container"
@@ -89,10 +104,10 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                             this.props.Document.isBackground ? `0px 0px 50px 50px ${this.clusterColor}` :
                                 `${this.clusterColor} ${StrCast(this.props.Document.boxShadow, `0vw 0vw ${50 / this.props.ContentScaling()}px`)}`) : undefined,
                     borderRadius: this.borderRounding(),
-                    transform: this.transform,
+                    transform: txf,
                     transition: hasPosition ? "transform 1s" : StrCast(this.props.Document.transition),
-                    width: this.width,
-                    height: this.height,
+                    width: w,
+                    height: h,
                     zIndex: this.Document.zIndex || 0,
                 }} >
                 <DocumentView {...this.props}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index b60730a6b..1763c664e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -758,9 +758,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             });
         }
         let showTextTitle = showTitle && StrCast(this.layoutDoc.layout).startsWith("<FormattedTextBox") ? showTitle : undefined;
-        let brushDegree = Doc.IsBrushedDegree(this.props.Document);
         let fullDegree = Doc.isBrushedHighlightedDegree(this.props.Document);
-        // console.log(fullDegree)
         let borderRounding = StrCast(Doc.GetProto(this.props.Document).borderRounding);
         let localScale = this.props.ScreenToLocalTransform().Scale * fullDegree;
         return (
diff --git a/src/server/index.ts b/src/server/index.ts
index d2c6584cc..6472ffb93 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -447,7 +447,7 @@ function LoadPage(file: string, pageNumber: number, res: Response) {
             console.log(pageNumber);
             pdf.getPage(pageNumber).then((page: Pdfjs.PDFPageProxy) => {
                 console.log("reading " + page);
-                let viewport = page.getViewport({scale: 1});
+                let viewport = page.getViewport(1 as any);
                 let canvasAndContext = factory.create(viewport.width, viewport.height);
                 let renderContext = {
                     canvasContext: canvasAndContext.context,
-- 
cgit v1.2.3-70-g09d2

