From 4859d4e3f5827c3341d43d19a5309d2ec25ab67b Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 1 Apr 2020 17:15:14 -0400
Subject: fixed warnings and some compile errors.  Made a key value layout and
 extened DocumentBox to have a childLayoutKey field

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

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

diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index e673189f9..c6fb9ad0b 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -39,7 +39,7 @@ library.add(faCheckCircle);
 library.add(faCloudUploadAlt);
 library.add(faSyncAlt);
 library.add(faShare);
-library.add(faPhotoVideo)
+library.add(faPhotoVideo);
 
 const cloud: IconProp = "cloud-upload-alt";
 const fetch: IconProp = "sync-alt";
-- 
cgit v1.2.3-70-g09d2


From 6ae33795b8d23a5dd14593ba8963cf14ec0b2a0e Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 1 Apr 2020 20:56:27 -0400
Subject: fixed document box to have sizable borders using x/ypadding.  enabled
 upSelector to select documentBox

---
 src/client/views/DocumentButtonBar.tsx  |  2 +-
 src/client/views/nodes/DocumentBox.scss |  4 --
 src/client/views/nodes/DocumentBox.tsx  | 77 +++++++++++++++++++--------------
 3 files changed, 46 insertions(+), 37 deletions(-)

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

diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index c6fb9ad0b..b0c701b65 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -312,7 +312,7 @@ export class DocumentButtonBar extends React.Component<{ views: (DocumentView |
     render() {
         if (!this.view0) return (null);
 
-        const isText = this.view0.props.Document.data instanceof RichTextField; // bcz: Todo - can't assume layout is using the 'data' field.  need to add fieldKey to DocumentView
+        const isText = this.view0.props.Document[Doc.LayoutFieldKey(this.view0.props.Document)] instanceof RichTextField;
         const considerPull = isText && this.considerGoogleDocsPull;
         const considerPush = isText && this.considerGoogleDocsPush;
         return <div className="documentButtonBar">
diff --git a/src/client/views/nodes/DocumentBox.scss b/src/client/views/nodes/DocumentBox.scss
index b7d06b364..6fc87e4f1 100644
--- a/src/client/views/nodes/DocumentBox.scss
+++ b/src/client/views/nodes/DocumentBox.scss
@@ -3,13 +3,9 @@
     height: 100%;
     pointer-events: all;
     background: gray;
-    border: #00000021 solid 15px;
-    border-top: #0000005e inset 15px;
-    border-bottom: #0000005e outset 15px;
     .documentBox-lock {
         margin: auto;
         color: white;
-        margin-top: -15px;
         position: absolute;
     }
 }
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentBox.tsx b/src/client/views/nodes/DocumentBox.tsx
index 655dc5de2..9d1c08389 100644
--- a/src/client/views/nodes/DocumentBox.tsx
+++ b/src/client/views/nodes/DocumentBox.tsx
@@ -5,7 +5,7 @@ import { Doc, Field } from "../../../new_fields/Doc";
 import { documentSchema } from "../../../new_fields/documentSchemas";
 import { makeInterface } from "../../../new_fields/Schema";
 import { ComputedField } from "../../../new_fields/ScriptField";
-import { Cast, StrCast } from "../../../new_fields/Types";
+import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
 import { emptyPath } from "../../../Utils";
 import { ContextMenu } from "../ContextMenu";
 import { ContextMenuProps } from "../ContextMenuItem";
@@ -85,13 +85,15 @@ export class DocumentBox extends DocAnnotatableComponent<FieldViewProps, DocBoxS
         (e.nativeEvent as any).formattedHandled = true;
         e.stopPropagation();
     }
+    get xPad() { return NumCast(this.props.Document._xPadding); }
+    get yPad() { return NumCast(this.props.Document._yPadding); }
     onClick = (e: React.MouseEvent) => {
         let hitWidget: boolean | undefined = false;
-        if (this._contRef.current!.getBoundingClientRect().top + 15 > e.clientY) hitWidget = (() => { this.props.select(false); return true; })();
-        else if (this._contRef.current!.getBoundingClientRect().bottom - 15 < e.clientY) hitWidget = (() => { this.props.select(false); return true; })();
+        if (this._contRef.current!.getBoundingClientRect().top + this.yPad > e.clientY) hitWidget = (() => { this.props.select(false); return true; })();
+        else if (this._contRef.current!.getBoundingClientRect().bottom - this.yPad < e.clientY) hitWidget = (() => { this.props.select(false); return true; })();
         else {
-            if (this._contRef.current!.getBoundingClientRect().left + 15 > e.clientX) hitWidget = this.prevSelection();
-            if (this._contRef.current!.getBoundingClientRect().right - 15 < e.clientX) hitWidget = this.nextSelection();
+            if (this._contRef.current!.getBoundingClientRect().left + this.xPad > e.clientX) hitWidget = this.prevSelection();
+            if (this._contRef.current!.getBoundingClientRect().right - this.xPad < e.clientX) hitWidget = this.nextSelection();
         }
         if (hitWidget) {
             (e.nativeEvent as any).formattedHandled = true;
@@ -99,39 +101,50 @@ export class DocumentBox extends DocAnnotatableComponent<FieldViewProps, DocBoxS
         }
     }
     _contRef = React.createRef<HTMLDivElement>();
-    pwidth = () => this.props.PanelWidth() - 30;
-    pheight = () => this.props.PanelHeight() - 30;
-    getTransform = () => this.props.ScreenToLocalTransform().translate(-15, -15);
+    pwidth = () => this.props.PanelWidth() - 2 * this.xPad;
+    pheight = () => this.props.PanelHeight() - 2 * this.yPad;
+    getTransform = () => this.props.ScreenToLocalTransform().translate(-this.xPad, -this.yPad);
+    get renderContents() {
+        const containedDoc = this.contentDoc[this.props.fieldKey];
+        const contents = !(containedDoc instanceof Doc) ? (null) : <ContentFittingDocumentView
+            Document={containedDoc}
+            DataDocument={undefined}
+            LibraryPath={emptyPath}
+            CollectionView={this as any} // bcz: hack!  need to pass a prop that can be used to select the container (ie, 'this') when the up selector in document decorations is clicked.  currently, the up selector allows only a containing collection to be selected
+            fitToBox={this.props.fitToBox}
+            layoutKey={StrCast(this.props.Document.childLayoutKey)}
+            addDocument={this.props.addDocument}
+            moveDocument={this.props.moveDocument}
+            removeDocument={this.props.removeDocument}
+            addDocTab={this.props.addDocTab}
+            pinToPres={this.props.pinToPres}
+            getTransform={this.getTransform}
+            renderDepth={this.props.renderDepth + 1}
+            PanelWidth={this.pwidth}
+            PanelHeight={this.pheight}
+            focus={this.props.focus}
+            active={this.props.active}
+            dontRegisterView={!this.isSelectionLocked()}
+            whenActiveChanged={this.props.whenActiveChanged}
+        />;
+        return contents;
+    }
     render() {
         TraceMobx();
-        const containedDoc = this.contentDoc[this.props.fieldKey];
         return <div className="documentBox-container" ref={this._contRef}
             onContextMenu={this.specificContextMenu}
             onPointerDown={this.onPointerDown} onClick={this.onClick}
-            style={{ background: StrCast(this.props.Document.backgroundColor) }}>
-            <div className="documentBox-lock" onClick={this.onLockClick}>
+            style={{
+                background: StrCast(this.props.Document.backgroundColor),
+                border: `#00000021 solid ${this.xPad}px`,
+                borderTop: `#0000005e solid ${this.yPad}px`,
+                borderBottom: `#0000005e solid ${this.yPad}px`,
+            }}>
+            <div className="documentBox-lock" onClick={this.onLockClick}
+                style={{ marginTop: - this.yPad }}>
                 <FontAwesomeIcon icon={this.isSelectionLocked() ? "lock" : "unlock"} size="sm" />
             </div>
-            {!(containedDoc instanceof Doc) ? (null) : <ContentFittingDocumentView
-                Document={containedDoc}
-                DataDocument={undefined}
-                LibraryPath={emptyPath}
-                fitToBox={this.props.fitToBox}
-                layoutKey={StrCast(this.props.Document.childLayoutKey)}
-                addDocument={this.props.addDocument}
-                moveDocument={this.props.moveDocument}
-                removeDocument={this.props.removeDocument}
-                addDocTab={this.props.addDocTab}
-                pinToPres={this.props.pinToPres}
-                getTransform={this.getTransform}
-                renderDepth={this.props.renderDepth + 1}
-                PanelWidth={this.pwidth}
-                PanelHeight={this.pheight}
-                focus={this.props.focus}
-                active={this.props.active}
-                dontRegisterView={!this.isSelectionLocked()}
-                whenActiveChanged={this.props.whenActiveChanged}
-            />}
-        </div>;
+            {this.renderContents}
+        </div >;
     }
 }
-- 
cgit v1.2.3-70-g09d2


From cf77e5f861c0927956e5453873839c81f0229374 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Wed, 1 Apr 2020 23:24:12 -0400
Subject: made it possible to link from one text selection to another

---
 src/client/util/DragManager.ts                  |  1 +
 src/client/views/DocumentButtonBar.tsx          |  9 +++-----
 src/client/views/nodes/DocumentContentsView.tsx |  4 +++-
 src/client/views/nodes/DocumentView.tsx         |  7 +++++-
 src/client/views/nodes/FormattedTextBox.tsx     | 29 +++++++++++++++++++++++++
 5 files changed, 42 insertions(+), 8 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 63a11c85a..8d3f6751e 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -148,6 +148,7 @@ export namespace DragManager {
         linkSourceDocument: Doc;
         dontClearTextBox?: boolean;
         linkDocument?: Doc;
+        linkDropCallback?: (data: LinkDragData) => void;
     }
     export class ColumnDragData {
         constructor(colKey: SchemaHeaderField) {
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index b0c701b65..b95cc6627 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -4,12 +4,10 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { action, computed, observable, runInAction } from "mobx";
 import { observer } from "mobx-react";
 import { Doc, DocListCast } from "../../new_fields/Doc";
-import { Id } from '../../new_fields/FieldSymbols';
 import { RichTextField } from '../../new_fields/RichTextField';
 import { NumCast, StrCast } from "../../new_fields/Types";
 import { emptyFunction } from "../../Utils";
 import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils';
-import RichTextMenu from '../util/RichTextMenu';
 import { UndoManager } from "../util/UndoManager";
 import { CollectionDockingView, DockedFrameRenderer } from './collections/CollectionDockingView';
 import { ParentDocSelector } from './collections/ParentDocumentSelector';
@@ -121,10 +119,9 @@ export class DocumentButtonBar extends React.Component<{ views: (DocumentView |
                     const linkDoc = dropEv.linkDragData?.linkDocument as Doc; // equivalent to !dropEve.aborted since linkDocument is only assigned on a completed drop
                     if (this.view0 && linkDoc) {
                         Doc.GetProto(linkDoc).linkRelationship = "hyperlink";
-
-                        const anchor2Title = linkDoc.anchor2 instanceof Doc ? StrCast(linkDoc.anchor2.title) : "-untitled-";
-                        const anchor2Id = linkDoc.anchor2 instanceof Doc ? linkDoc.anchor2[Id] : "";
-                        const text = RichTextMenu.Instance.MakeLinkToSelection(linkDoc[Id], anchor2Title, e.ctrlKey ? "onRight" : "inTab", anchor2Id);
+                        dropEv.linkDragData?.linkDropCallback?.(dropEv.linkDragData);
+                        runInAction(() => this.view0!._link = linkDoc);
+                        setTimeout(action(() => this.view0!._link = undefined), 0);
                     }
                     linkDrag?.end();
                 },
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index c250da874..da035a6ce 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -58,7 +58,9 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
     select: (ctrl: boolean) => void,
     layoutKey: string,
     forceLayout?: string,
-    forceFieldKey?: string
+    forceFieldKey?: string,
+    hideOnLeave?:boolean,
+    makeLink?: () => Opt<Doc>;
 }> {
     @computed get layout(): string {
         TraceMobx();
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 7770a5caf..d8bbd88ce 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -40,7 +40,6 @@ import { ScriptBox } from '../ScriptBox';
 import { ScriptingRepl } from '../ScriptingRepl';
 import { DocumentContentsView } from "./DocumentContentsView";
 import "./DocumentView.scss";
-import { FormattedTextBox } from './FormattedTextBox';
 import React = require("react");
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { SchemaHeaderField } from '../../../new_fields/SchemaHeaderField';
@@ -967,6 +966,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
             Document={this.props.Document}
             DataDoc={this.props.DataDoc}
             LayoutDoc={this.props.LayoutDoc}
+            makeLink={this.makeLink}
             fitToBox={this.props.fitToBox}
             LibraryPath={this.props.LibraryPath}
             addDocument={this.props.addDocument}
@@ -1002,6 +1002,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
         const ept = Doc.AreProtosEqual(this.props.Document, Cast(linkDoc.anchor1, Doc) as Doc) ? linkDoc.anchor1_timecode : linkDoc.anchor2_timecode;
         return anchor.type === DocumentType.AUDIO && NumCast(ept) ? false : true;
     }
+c
+    @observable _link:Opt<Doc>;
+    makeLink = () => { 
+        return this._link;
+    }
 
     @computed get innards() {
         TraceMobx();
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index bc43beab9..241345f3e 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -54,6 +54,7 @@ library.add(faSmile, faTextHeight, faUpload);
 
 export interface FormattedTextBoxProps {
     hideOnLeave?: boolean;
+    makeLink?: () => Opt<Doc>;
 }
 
 const richTextSchema = createSchema({
@@ -91,6 +92,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
     private _pullReactionDisposer: Opt<IReactionDisposer>;
     private _pushReactionDisposer: Opt<IReactionDisposer>;
     private _buttonBarReactionDisposer: Opt<IReactionDisposer>;
+    private _linkMakerDisposer: Opt<IReactionDisposer>;
     private _scrollDisposer: Opt<IReactionDisposer>;
     private dropDisposer?: DragManager.DragDropDisposer;
 
@@ -282,8 +284,16 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
                 e.stopPropagation();
                 // }
             } // otherwise, fall through to outer collection to handle drop
+        } else if (de.complete.linkDragData) {
+            de.complete.linkDragData.linkDropCallback = this.linkDrop;
         }
     }
+    linkDrop = (data: DragManager.LinkDragData) => {
+        const linkDoc = data.linkDocument!;
+        const anchor1Title = linkDoc.anchor1 instanceof Doc ? StrCast(linkDoc.anchor1.title) : "-untitled-";
+        const anchor1Id = linkDoc.anchor1 instanceof Doc ? linkDoc.anchor1[Id] : "";
+        this.makeLinkToSelection(linkDoc[Id], anchor1Title, "onRight", anchor1Id)
+    }
 
     getNodeEndpoints(context: Node, node: Node): { from: number, to: number } | null {
         let offset = 0;
@@ -513,6 +523,13 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
         };
     }
 
+    makeLinkToSelection(linkDocId: string, title: string, location: string, targetDocId: string) {
+        if (this._editorView) {
+            const link = this._editorView.state.schema.marks.link.create({ href: Utils.prepend("/doc/" + linkDocId), title: title, location: location, linkId: linkDocId, targetId: targetDocId });
+            this._editorView.dispatch(this._editorView.state.tr.removeMark(this._editorView.state.selection.from, this._editorView.state.selection.to, this._editorView.state.schema.marks.link).
+                addMark(this._editorView.state.selection.from, this._editorView.state.selection.to, link));
+        }
+    }
     componentDidMount() {
         this._buttonBarReactionDisposer = reaction(
             () => DocumentButtonBar.Instance,
@@ -523,6 +540,17 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
                 }
             }
         );
+        this._linkMakerDisposer = reaction(
+            () => this.props.makeLink?.(),
+            (linkDoc: Opt<Doc>) => {
+                if (linkDoc) {
+                    const anchor2Title = linkDoc.anchor2 instanceof Doc ? StrCast(linkDoc.anchor2.title) : "-untitled-";
+                    const anchor2Id = linkDoc.anchor2 instanceof Doc ? linkDoc.anchor2[Id] : "";
+                    this.makeLinkToSelection(linkDoc[Id], anchor2Title, "onRight", anchor2Id);
+                }
+            },
+            { fireImmediately: true }
+        );
 
         this._reactionDisposer = reaction(
             () => {
@@ -858,6 +886,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
         this._searchReactionDisposer?.();
         this._recordReactionDisposer?.();
         this._buttonBarReactionDisposer?.();
+        this._linkMakerDisposer?.();
         this._editorView?.destroy();
     }
 
-- 
cgit v1.2.3-70-g09d2

