From d5304e13839830c60c0c5698849535b0605e3c32 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 18 Mar 2019 10:28:43 -0400
Subject: fixed drag drop and loading of pdfs

---
 src/client/views/nodes/DocumentView.tsx | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'src/client/views/nodes/DocumentView.tsx')

diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 6a3967b3b..fbd58ef7e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -165,7 +165,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
             const [left, top] = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
             let dragData: { [id: string]: any } = {};
             dragData["documentView"] = this;
-            dragData[dropAliasOfDraggedDoc ? "documentToAlias" : "document"] = this.props.Document;
+            if (dropAliasOfDraggedDoc)
+                dragData["documentToAlias"] = this.props.Document;
+            dragData["document"] = this.props.Document;
             dragData["xOffset"] = x - left;
             dragData["yOffset"] = y - top;
             DragManager.StartDrag(this._mainCont.current, dragData, {
-- 
cgit v1.2.3-70-g09d2


From 8418b842b16da68150243e1750aa8b40eb8a8792 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 18 Mar 2019 11:48:24 -0400
Subject: fixed removing from schemas.  fixed dragging link button to move
 quickly. cleaned up drag/drop code a little

---
 src/client/util/DragManager.ts                     | 12 +++-----
 src/client/views/DocumentDecorations.tsx           | 14 ++++-----
 src/client/views/InkingControl.tsx                 |  3 +-
 .../views/collections/CollectionFreeFormView.tsx   |  4 +--
 src/client/views/collections/CollectionPDFView.tsx |  2 +-
 .../views/collections/CollectionSchemaView.tsx     |  4 +--
 .../views/collections/CollectionVideoView.tsx      |  2 +-
 src/client/views/collections/CollectionView.tsx    |  7 +++--
 .../views/collections/CollectionViewBase.tsx       | 36 ++++++++--------------
 src/client/views/collections/MarqueeView.tsx       | 15 +++++++--
 src/client/views/nodes/DocumentView.tsx            | 16 +++++-----
 11 files changed, 57 insertions(+), 58 deletions(-)

(limited to 'src/client/views/nodes/DocumentView.tsx')

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index c0abec407..54784f2d2 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -2,18 +2,18 @@ import { DocumentDecorations } from "../views/DocumentDecorations";
 import { CollectionDockingView } from "../views/collections/CollectionDockingView";
 import { Document } from "../../fields/Document"
 import { action } from "mobx";
-import { DocumentView } from "../views/nodes/DocumentView";
 import { ImageField } from "../../fields/ImageField";
 import { KeyStore } from "../../fields/KeyStore";
+import { CollectionView } from "../views/collections/CollectionView";
 
-export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document) {
+export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, removeFunc: (containingCollection: CollectionView) => void = () => { }) {
     let onRowMove = action((e: PointerEvent): void => {
         e.stopPropagation();
         e.preventDefault();
 
         document.removeEventListener("pointermove", onRowMove);
         document.removeEventListener('pointerup', onRowUp);
-        DragManager.StartDrag(_reference.current!, { document: docFunc() });
+        DragManager.StartDrag(_reference.current!, { draggedDocument: docFunc(), removeDocument: removeFunc });
     });
     let onRowUp = action((e: PointerEvent): void => {
         document.removeEventListener("pointermove", onRowMove);
@@ -122,9 +122,7 @@ export namespace DragManager {
         // bcz: PDFs don't show up if you clone them because they contain a canvas.
         //      however, PDF's have a thumbnail field that contains an image of their canvas.
         //      So we replace the pdf's canvas with the image thumbnail
-        const docView: DocumentView = dragData["documentView"];
-        const doc: Document = dragData["document"];
-
+        const doc: Document = dragData["draggedDocument"];
         if (doc) {
             var pdfBox = dragElement.getElementsByClassName("pdfBox-cont")[0] as HTMLElement;
             let thumbnail = doc.GetT(KeyStore.Thumbnail, ImageField);
@@ -138,7 +136,6 @@ export namespace DragManager {
             }
         }
 
-
         dragDiv.appendChild(dragElement);
 
         let hideSource = false;
@@ -191,6 +188,7 @@ export namespace DragManager {
         if (!target) {
             return;
         }
+        dragData["droppedDocument"] = dragData["aliasOnDrop"] ? (dragData["draggedDocument"] as Document).CreateAlias() : dragData["draggedDocument"];
         target.dispatchEvent(new CustomEvent<DropEvent>("dashOnDrop", {
             bubbles: true,
             detail: {
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 3bdb7d5b3..1145fbe7f 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -77,7 +77,6 @@ export class DocumentDecorations extends React.Component {
     }
 
     onLinkButtonUp = (e: PointerEvent): void => {
-        console.log("up");
         document.removeEventListener("pointermove", this.onLinkButtonMoved)
         document.removeEventListener("pointerup", this.onLinkButtonUp)
         e.stopPropagation();
@@ -85,10 +84,11 @@ export class DocumentDecorations extends React.Component {
 
 
     onLinkButtonMoved = (e: PointerEvent): void => {
-        console.log("moved");
-        let dragData: { [id: string]: any } = {};
-        dragData["linkSourceDoc"] = SelectionManager.SelectedDocuments()[0];
         if (this._linkButton.current != null) {
+            document.removeEventListener("pointermove", this.onLinkButtonMoved)
+            document.removeEventListener("pointerup", this.onLinkButtonUp)
+            let dragData: { [id: string]: any } = {};
+            dragData["linkSourceDoc"] = SelectionManager.SelectedDocuments()[0];
             DragManager.StartDrag(this._linkButton.current, dragData, {
                 handlers: {
                     dragComplete: action(() => { }),
@@ -96,8 +96,6 @@ export class DocumentDecorations extends React.Component {
                 hideSource: false
             })
         }
-        document.removeEventListener("pointermove", this.onLinkButtonMoved)
-        document.removeEventListener("pointerup", this.onLinkButtonUp)
         e.stopPropagation();
     }
 
@@ -217,7 +215,7 @@ export class DocumentDecorations extends React.Component {
                     <LinkMenu docView={selFirst} changeFlyout={this.changeFlyoutContent}>
                     </LinkMenu>
                 }>
-                <div className={"linkButton-" + (selFirst.props.Document.GetData(KeyStore.LinkedToDocs, ListField, []).length ? "nonempty" : "empty")} onPointerDown={this.onLinkButtonDown} ref={this._linkButton}>{linkCount}</div>
+                <div className={"linkButton-" + (selFirst.props.Document.GetData(KeyStore.LinkedToDocs, ListField, []).length ? "nonempty" : "empty")} onPointerDown={this.onLinkButtonDown} >{linkCount}</div>
             </Flyout>);
         }
         return (
@@ -237,7 +235,7 @@ export class DocumentDecorations extends React.Component {
                 <div id="documentDecorations-bottomResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
                 <div id="documentDecorations-bottomRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div>
 
-                <div title="View Links" className="linkFlyout">{linkButton}</div>
+                <div title="View Links" className="linkFlyout" ref={this._linkButton}>{linkButton}</div>
 
             </div >
         )
diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx
index 6616f68d8..ad6bbd476 100644
--- a/src/client/views/InkingControl.tsx
+++ b/src/client/views/InkingControl.tsx
@@ -11,6 +11,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { faPen, faHighlighter, faEraser, faBan } from '@fortawesome/free-solid-svg-icons';
 import { SelectionManager } from "../util/SelectionManager";
 import { KeyStore } from "../../fields/KeyStore";
+import { TextField } from "../../fields/TextField";
 
 library.add(faPen, faHighlighter, faEraser, faBan);
 
@@ -39,7 +40,7 @@ export class InkingControl extends React.Component {
         if (SelectionManager.SelectedDocuments().length == 1) {
             var sdoc = SelectionManager.SelectedDocuments()[0];
             if (sdoc.props.ContainingCollectionView && sdoc.props.ContainingCollectionView) {
-                sdoc.props.Document.SetText(KeyStore.BackgroundColor, color.hex);
+                sdoc.props.Document.SetOnPrototype(KeyStore.BackgroundColor, new TextField(color.hex));
             }
         }
     }
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 728076ef8..85ea2d121 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -28,7 +28,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
         // mark this collection so that when the text box is created we can send it the SelectOnLoad prop to focus itself
         this._selectOnLoaded = newBox.Id;
         //set text to be the typed key and get focus on text box
-        this.props.addDocument(newBox);
+        this.props.addDocument(newBox, false);
         //remove cursor from screen
         this.PreviewCursorVisible = false;
     }
@@ -79,7 +79,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
         let screenX = de.x - (de.data["xOffset"] as number || 0);
         let screenY = de.y - (de.data["yOffset"] as number || 0);
         const [x, y] = this.getTransform().transformPoint(screenX, screenY);
-        let doc: Document = de.data["document"];
+        let doc: Document = de.data["droppedDocument"];
         if (doc) {
             doc.SetNumber(KeyStore.X, x);
             doc.SetNumber(KeyStore.Y, y);
diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx
index 124d82c8b..e64b4c945 100644
--- a/src/client/views/collections/CollectionPDFView.tsx
+++ b/src/client/views/collections/CollectionPDFView.tsx
@@ -38,7 +38,7 @@ export class CollectionPDFView extends React.Component<CollectionViewProps> {
     public SelectedDocs: FieldId[] = []
     public active: () => boolean = () => CollectionView.Active(this);
 
-    addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); }
+    addDocument = (doc: Document, allowDuplicates: boolean): void => { CollectionView.AddDocument(this.props, doc, allowDuplicates); }
     removeDocument = (doc: Document): boolean => { return CollectionView.RemoveDocument(this.props, doc); }
 
     specificContextMenu = (e: React.MouseEvent): void => {
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index f88a62a0f..ced08a14e 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -14,7 +14,7 @@ import { EditableView } from "../EditableView";
 import { DocumentView } from "../nodes/DocumentView";
 import { FieldView, FieldViewProps } from "../nodes/FieldView";
 import "./CollectionSchemaView.scss";
-import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
+import { COLLECTION_BORDER_WIDTH, CollectionView } from "./CollectionView";
 import { CollectionViewBase } from "./CollectionViewBase";
 import { setupDrag } from "../../util/DragManager";
 
@@ -47,7 +47,7 @@ export class CollectionSchemaView extends CollectionViewBase {
             <FieldView {...props} />
         )
         let reference = React.createRef<HTMLDivElement>();
-        let onItemDown = setupDrag(reference, () => props.doc);
+        let onItemDown = setupDrag(reference, () => props.doc, (containingCollection: CollectionView) => this.props.removeDocument(props.doc));
         return (
             <div className="collectionSchemaView-cellContents" onPointerDown={onItemDown} style={{ height: "36px" }} key={props.doc.Id} ref={reference}>
                 <EditableView contents={contents}
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 8fc1a1b4d..05f759967 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -44,7 +44,7 @@ export class CollectionVideoView extends React.Component<CollectionViewProps> {
     public SelectedDocs: FieldId[] = []
     public active: () => boolean = () => CollectionView.Active(this);
 
-    addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); }
+    addDocument = (doc: Document, allowDuplicates: boolean): void => { CollectionView.AddDocument(this.props, doc, allowDuplicates); }
     removeDocument = (doc: Document): boolean => { return CollectionView.RemoveDocument(this.props, doc); }
 
     specificContextMenu = (e: React.MouseEvent): void => {
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 40acf466e..303099c16 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -36,7 +36,7 @@ export class CollectionView extends React.Component<CollectionViewProps> {
     @observable
     public SelectedDocs: FieldId[] = [];
     public active: () => boolean = () => CollectionView.Active(this);
-    addDocument = (doc: Document): void => { CollectionView.AddDocument(this.props, doc); }
+    addDocument = (doc: Document, allowDuplicates: boolean): void => { CollectionView.AddDocument(this.props, doc, allowDuplicates); }
     removeDocument = (doc: Document): boolean => { return CollectionView.RemoveDocument(this.props, doc); }
     get subView() { return CollectionView.SubView(this); }
 
@@ -48,12 +48,13 @@ export class CollectionView extends React.Component<CollectionViewProps> {
     }
 
     @action
-    public static AddDocument(props: CollectionViewProps, doc: Document) {
+    public static AddDocument(props: CollectionViewProps, doc: Document, allowDuplicates: boolean) {
         doc.SetNumber(KeyStore.Page, props.Document.GetNumber(KeyStore.CurPage, -1));
         if (props.Document.Get(props.fieldKey) instanceof Field) {
             //TODO This won't create the field if it doesn't already exist
             const value = props.Document.GetData(props.fieldKey, ListField, new Array<Document>())
-            value.push(doc);
+            if (!value.some(v => v.Id == doc.Id) || allowDuplicates)
+                value.push(doc);
         } else {
             props.Document.SetOnPrototype(props.fieldKey, new ListField([doc]));
         }
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 3d1a76a07..0358b5907 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -27,7 +27,7 @@ export interface CollectionViewProps {
 }
 export interface SubCollectionViewProps extends CollectionViewProps {
     active: () => boolean;
-    addDocument: (doc: Document) => void;
+    addDocument: (doc: Document, allowDuplicates: boolean) => void;
     removeDocument: (doc: Document) => boolean;
     CollectionView: CollectionView;
 }
@@ -46,28 +46,16 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
     @undoBatch
     @action
     protected drop(e: Event, de: DragManager.DropEvent) {
-        let docToAlias = de.data["documentToAlias"];
-        let docView = de.data["documentView"];
-        let doc = docToAlias ? docToAlias.CreateAlias() : de.data["document"];
-        if (docToAlias) {
-            [KeyStore.Width, KeyStore.Height].map(key =>
-                docToAlias.GetTAsync(key, NumberField, (f: Opt<NumberField>) => {
-                    if (f) {
-                        doc.SetNumber(key, f.Data)
-                    }
-                })
-            );
-            de.data["document"] = doc;
-            this.props.addDocument(doc);
-        } else if (docView) {
-            if (doc && docView.props.RemoveDocument && docView.props.ContainingCollectionView !== this.props.CollectionView) {
-                docView.props.RemoveDocument(doc);
-                this.props.removeDocument(doc); // bcz: not good -- want to check if it's there and then add if it isn't
-                this.props.addDocument(doc);
+        let dropped = de.data["droppedDocument"];
+        if (dropped) {
+            if (de.data["aliasOnDrop"]) {
+                let dragged = de.data["draggedDocument"];
+                [KeyStore.Width, KeyStore.Height, KeyStore.CurPage].map(key =>
+                    dragged.GetTAsync(key, NumberField, (f: Opt<NumberField>) => f ? dropped.SetNumber(key, f.Data) : null));
+            } else if (de.data["removeDocument"]) {
+                de.data["removeDocument"](this.props.CollectionView);
             }
-        } else if (doc) {
-            this.props.removeDocument(doc); // bcz: not good -- want to check if it's there and then add if it isn't
-            this.props.addDocument(doc);
+            this.props.addDocument(dropped, false);
         }
         e.stopPropagation();
     }
@@ -89,7 +77,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
             console.log("not good");
             let htmlDoc = Documents.HtmlDocument(html, { ...options, width: 300, height: 300 });
             htmlDoc.SetText(KeyStore.DocumentText, text);
-            this.props.addDocument(htmlDoc);
+            this.props.addDocument(htmlDoc, false);
             return;
         }
 
@@ -99,7 +87,7 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
             const upload = window.location.origin + "/upload";
             let item = e.dataTransfer.items[i];
             if (item.kind === "string" && item.type.indexOf("uri") != -1) {
-                e.dataTransfer.items[i].getAsString(action((s: string) => this.props.addDocument(Documents.WebDocument(s, options))))
+                e.dataTransfer.items[i].getAsString(action((s: string) => this.props.addDocument(Documents.WebDocument(s, options), false)))
             }
             let type = item.type
             console.log(type)
diff --git a/src/client/views/collections/MarqueeView.tsx b/src/client/views/collections/MarqueeView.tsx
index f5c83a934..8c2f3443c 100644
--- a/src/client/views/collections/MarqueeView.tsx
+++ b/src/client/views/collections/MarqueeView.tsx
@@ -17,7 +17,7 @@ interface MarqueeViewProps {
     getMarqueeTransform: () => Transform;
     getTransform: () => Transform;
     container: CollectionFreeFormView;
-    addDocument: (doc: Document) => void;
+    addDocument: (doc: Document, allowDuplicates: false) => void;
     activeDocuments: () => Document[];
     selectDocuments: (docs: Document[]) => void;
     removeDocument: (doc: Document) => boolean;
@@ -111,7 +111,18 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
             let liftedInk = this.marqueeInkSelect(true);
             this.props.container.props.Document.SetData(KeyStore.Ink, this.marqueeInkSelect(false), InkField);
             //setTimeout(() => {
-            this.props.addDocument(Documents.FreeformDocument(selected, { x: bounds.left, y: bounds.top, panx: 0, pany: 0, width: bounds.width, backgroundColor: "Transparent", height: bounds.height, ink: liftedInk, title: "a nested collection" }));
+            let newCollection = Documents.FreeformDocument(selected, {
+                x: bounds.left,
+                y: bounds.top,
+                panx: 0,
+                pany: 0,
+                width: bounds.width,
+                height: bounds.height,
+                backgroundColor: "Transparent",
+                ink: liftedInk,
+                title: "a nested collection"
+            });
+            this.props.addDocument(newCollection, false);
             // }, 100);
             this.cleanupInteractions();
         }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index fbd58ef7e..e98815fa6 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -23,7 +23,7 @@ import React = require("react");
 export interface DocumentViewProps {
     ContainingCollectionView: Opt<CollectionView>;
     Document: Document;
-    AddDocument?: (doc: Document) => void;
+    AddDocument?: (doc: Document, allowDuplicates: boolean) => void;
     RemoveDocument?: (doc: Document) => boolean;
     ScreenToLocalTransform: () => Transform;
     isTopMost: boolean;
@@ -164,12 +164,15 @@ export class DocumentView extends React.Component<DocumentViewProps> {
         if (this._mainCont.current) {
             const [left, top] = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
             let dragData: { [id: string]: any } = {};
-            dragData["documentView"] = this;
-            if (dropAliasOfDraggedDoc)
-                dragData["documentToAlias"] = this.props.Document;
-            dragData["document"] = this.props.Document;
+            dragData["aliasOnDrop"] = dropAliasOfDraggedDoc;
+            dragData["draggedDocument"] = this.props.Document;
             dragData["xOffset"] = x - left;
             dragData["yOffset"] = y - top;
+            dragData["removeDocument"] = (dropCollectionView: CollectionView) => {
+                if (this.props.RemoveDocument && this.props.ContainingCollectionView !== dropCollectionView) {
+                    this.props.RemoveDocument(this.props.Document);
+                }
+            }
             DragManager.StartDrag(this._mainCont.current, dragData, {
                 handlers: {
                     dragComplete: action(() => { }),
@@ -213,7 +216,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     fieldsClicked = (e: React.MouseEvent): void => {
         if (this.props.AddDocument) {
-            this.props.AddDocument(Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }));
+            this.props.AddDocument(Documents.KVPDocument(this.props.Document, { width: 300, height: 300 }), false);
         }
     }
     fullScreenClicked = (e: React.MouseEvent): void => {
@@ -232,7 +235,6 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
-        console.log("drop");
         const sourceDocView: DocumentView = de.data["linkSourceDoc"];
         if (!sourceDocView) {
             return;
-- 
cgit v1.2.3-70-g09d2


From 861614569c2d72e0ee9a6a698f3978f609a3b2bc Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Mon, 18 Mar 2019 12:54:08 -0400
Subject: added typings to DragManager's data

---
 src/client/util/DragManager.ts                     | 46 ++++++++++++++++++---
 src/client/views/DocumentDecorations.tsx           |  5 +--
 .../views/collections/CollectionFreeFormView.tsx   | 15 ++++---
 .../views/collections/CollectionViewBase.tsx       | 19 +++++----
 src/client/views/nodes/DocumentView.tsx            | 47 ++++++++++------------
 5 files changed, 80 insertions(+), 52 deletions(-)

(limited to 'src/client/views/nodes/DocumentView.tsx')

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 54784f2d2..753115f76 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -5,6 +5,7 @@ import { action } from "mobx";
 import { ImageField } from "../../fields/ImageField";
 import { KeyStore } from "../../fields/KeyStore";
 import { CollectionView } from "../views/collections/CollectionView";
+import { DocumentView } from "../views/nodes/DocumentView";
 
 export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc: () => Document, removeFunc: (containingCollection: CollectionView) => void = () => { }) {
     let onRowMove = action((e: PointerEvent): void => {
@@ -13,7 +14,9 @@ export function setupDrag(_reference: React.RefObject<HTMLDivElement>, docFunc:
 
         document.removeEventListener("pointermove", onRowMove);
         document.removeEventListener('pointerup', onRowUp);
-        DragManager.StartDrag(_reference.current!, { draggedDocument: docFunc(), removeDocument: removeFunc });
+        var dragData = new DragManager.DocumentDragData(docFunc());
+        dragData.removeDocument = removeFunc;
+        DragManager.StartDocumentDrag(_reference.current!, dragData);
     });
     let onRowUp = action((e: PointerEvent): void => {
         document.removeEventListener("pointermove", onRowMove);
@@ -70,11 +73,12 @@ export namespace DragManager {
     export interface DropOptions {
         handlers: DropHandlers;
     }
-
     export class DropEvent {
         constructor(readonly x: number, readonly y: number, readonly data: { [id: string]: any }) { }
     }
 
+
+
     export interface DropHandlers {
         drop: (e: Event, de: DropEvent) => void;
     }
@@ -96,7 +100,34 @@ export namespace DragManager {
         };
     }
 
-    export function StartDrag(ele: HTMLElement, dragData: { [id: string]: any }, options?: DragOptions) {
+    export class DocumentDragData {
+        constructor(dragDoc: Document) {
+            this.draggedDocument = dragDoc;
+            this.droppedDocument = dragDoc;
+        }
+        draggedDocument: Document;
+        droppedDocument: Document;
+        xOffset?: number;
+        yOffset?: number;
+        aliasOnDrop?: boolean;
+        removeDocument?: (collectionDrop: CollectionView) => void;
+        [id: string]: any;
+    }
+    export function StartDocumentDrag(ele: HTMLElement, dragData: DocumentDragData, options?: DragOptions) {
+        StartDrag(ele, dragData, options, (dropData: { [id: string]: any }) => dropData.droppedDocument = dragData.aliasOnDrop ? dragData.draggedDocument.CreateAlias() : dragData.draggedDocument);
+    }
+
+    export class LinkDragData {
+        constructor(linkSourceDoc: DocumentView) {
+            this.linkSourceDocumentView = linkSourceDoc;
+        }
+        linkSourceDocumentView: DocumentView;
+        [id: string]: any;
+    }
+    export function StartLinkDrag(ele: HTMLElement, dragData: LinkDragData, options?: DragOptions) {
+        StartDrag(ele, dragData, options);
+    }
+    function StartDrag(ele: HTMLElement, dragData: { [id: string]: any }, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) {
         if (!dragDiv) {
             dragDiv = document.createElement("div");
             dragDiv.className = "dragManager-dragDiv"
@@ -172,13 +203,13 @@ export namespace DragManager {
         }
         const upHandler = (e: PointerEvent) => {
             abortDrag();
-            FinishDrag(ele, e, dragData, options);
+            FinishDrag(ele, e, dragData, options, finishDrag);
         };
         document.addEventListener("pointermove", moveHandler, true);
         document.addEventListener("pointerup", upHandler);
     }
 
-    function FinishDrag(dragEle: HTMLElement, e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions) {
+    function FinishDrag(dragEle: HTMLElement, e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions, finishDrag?: (dragData: { [index: string]: any }) => void) {
         let parent = dragEle.parentElement;
         if (parent)
             parent.removeChild(dragEle);
@@ -188,7 +219,9 @@ export namespace DragManager {
         if (!target) {
             return;
         }
-        dragData["droppedDocument"] = dragData["aliasOnDrop"] ? (dragData["draggedDocument"] as Document).CreateAlias() : dragData["draggedDocument"];
+        if (finishDrag)
+            finishDrag(dragData);
+
         target.dispatchEvent(new CustomEvent<DropEvent>("dashOnDrop", {
             bubbles: true,
             detail: {
@@ -197,6 +230,7 @@ export namespace DragManager {
                 data: dragData
             }
         }));
+
         if (options) {
             options.handlers.dragComplete({});
         }
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 1145fbe7f..a8090dc8f 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -87,9 +87,8 @@ export class DocumentDecorations extends React.Component {
         if (this._linkButton.current != null) {
             document.removeEventListener("pointermove", this.onLinkButtonMoved)
             document.removeEventListener("pointerup", this.onLinkButtonUp)
-            let dragData: { [id: string]: any } = {};
-            dragData["linkSourceDoc"] = SelectionManager.SelectedDocuments()[0];
-            DragManager.StartDrag(this._linkButton.current, dragData, {
+            let dragData = new DragManager.LinkDragData(SelectionManager.SelectedDocuments()[0]);
+            DragManager.StartLinkDrag(this._linkButton.current, dragData, {
                 handlers: {
                     dragComplete: action(() => { }),
                 },
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 85ea2d121..7ab91ebaa 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -76,14 +76,13 @@ export class CollectionFreeFormView extends CollectionViewBase {
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
         super.drop(e, de);
-        let screenX = de.x - (de.data["xOffset"] as number || 0);
-        let screenY = de.y - (de.data["yOffset"] as number || 0);
-        const [x, y] = this.getTransform().transformPoint(screenX, screenY);
-        let doc: Document = de.data["droppedDocument"];
-        if (doc) {
-            doc.SetNumber(KeyStore.X, x);
-            doc.SetNumber(KeyStore.Y, y);
-            this.bringToFront(doc);
+        if (de.data instanceof DragManager.DocumentDragData) {
+            let screenX = de.x - (de.data.xOffset as number || 0);
+            let screenY = de.y - (de.data.yOffset as number || 0);
+            const [x, y] = this.getTransform().transformPoint(screenX, screenY);
+            de.data.droppedDocument.SetNumber(KeyStore.X, x);
+            de.data.droppedDocument.SetNumber(KeyStore.Y, y);
+            this.bringToFront(de.data.droppedDocument);
         }
     }
 
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 0358b5907..581853e67 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -6,12 +6,12 @@ import { KeyStore } from "../../../fields/KeyStore";
 import { FieldWaiting, Field, Opt } from "../../../fields/Field";
 import { undoBatch } from "../../util/UndoManager";
 import { DragManager } from "../../util/DragManager";
-import { DocumentView } from "../nodes/DocumentView";
 import { Documents, DocumentOptions } from "../../documents/Documents";
 import { Key } from "../../../fields/Key";
 import { Transform } from "../../util/Transform";
 import { CollectionView } from "./CollectionView";
 import { NumberField } from "../../../fields/NumberField";
+import { DocumentManager } from "../../util/DocumentManager";
 
 export interface CollectionViewProps {
     fieldKey: Key;
@@ -46,18 +46,17 @@ export class CollectionViewBase extends React.Component<SubCollectionViewProps>
     @undoBatch
     @action
     protected drop(e: Event, de: DragManager.DropEvent) {
-        let dropped = de.data["droppedDocument"];
-        if (dropped) {
-            if (de.data["aliasOnDrop"]) {
-                let dragged = de.data["draggedDocument"];
+        if (de.data instanceof DragManager.DocumentDragData) {
+            if (de.data.aliasOnDrop) {
+                let dragged = de.data.draggedDocument;
                 [KeyStore.Width, KeyStore.Height, KeyStore.CurPage].map(key =>
-                    dragged.GetTAsync(key, NumberField, (f: Opt<NumberField>) => f ? dropped.SetNumber(key, f.Data) : null));
-            } else if (de.data["removeDocument"]) {
-                de.data["removeDocument"](this.props.CollectionView);
+                    dragged.GetTAsync(key, NumberField, (f: Opt<NumberField>) => f ? de.data.droppedDocument.SetNumber(key, f.Data) : null));
+            } else if (de.data.removeDocument) {
+                de.data.removeDocument(this.props.CollectionView);
             }
-            this.props.addDocument(dropped, false);
+            this.props.addDocument(de.data.droppedDocument, false);
+            e.stopPropagation();
         }
-        e.stopPropagation();
     }
 
     @action
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index e98815fa6..9e34b2b60 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -163,17 +163,16 @@ export class DocumentView extends React.Component<DocumentViewProps> {
     startDragging(x: number, y: number, dropAliasOfDraggedDoc: boolean) {
         if (this._mainCont.current) {
             const [left, top] = this.props.ScreenToLocalTransform().inverse().transformPoint(0, 0);
-            let dragData: { [id: string]: any } = {};
-            dragData["aliasOnDrop"] = dropAliasOfDraggedDoc;
-            dragData["draggedDocument"] = this.props.Document;
-            dragData["xOffset"] = x - left;
-            dragData["yOffset"] = y - top;
-            dragData["removeDocument"] = (dropCollectionView: CollectionView) => {
+            let dragData = new DragManager.DocumentDragData(this.props.Document);
+            dragData.aliasOnDrop = dropAliasOfDraggedDoc;
+            dragData.xOffset = x - left;
+            dragData.yOffset = y - top;
+            dragData.removeDocument = (dropCollectionView: CollectionView) => {
                 if (this.props.RemoveDocument && this.props.ContainingCollectionView !== dropCollectionView) {
                     this.props.RemoveDocument(this.props.Document);
                 }
             }
-            DragManager.StartDrag(this._mainCont.current, dragData, {
+            DragManager.StartDocumentDrag(this._mainCont.current, dragData, {
                 handlers: {
                     dragComplete: action(() => { }),
                 },
@@ -235,27 +234,25 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     @action
     drop = (e: Event, de: DragManager.DropEvent) => {
-        const sourceDocView: DocumentView = de.data["linkSourceDoc"];
-        if (!sourceDocView) {
-            return;
-        }
-        let sourceDoc: Document = sourceDocView.props.Document;
-        let destDoc: Document = this.props.Document;
-        if (this.props.isTopMost) {
-            return;
-        }
-        let linkDoc: Document = new Document();
+        if (de.data instanceof DragManager.LinkDragData) {
+            let sourceDoc: Document = de.data.linkSourceDocumentView.props.Document;
+            let destDoc: Document = this.props.Document;
+            if (this.props.isTopMost) {
+                return;
+            }
+            let linkDoc: Document = new Document();
 
-        linkDoc.Set(KeyStore.Title, new TextField("New Link"));
-        linkDoc.Set(KeyStore.LinkDescription, new TextField(""));
-        linkDoc.Set(KeyStore.LinkTags, new TextField("Default"));
+            linkDoc.Set(KeyStore.Title, new TextField("New Link"));
+            linkDoc.Set(KeyStore.LinkDescription, new TextField(""));
+            linkDoc.Set(KeyStore.LinkTags, new TextField("Default"));
 
-        sourceDoc.GetOrCreateAsync(KeyStore.LinkedToDocs, ListField, field => { (field as ListField<Document>).Data.push(linkDoc) });
-        linkDoc.Set(KeyStore.LinkedToDocs, destDoc);
-        destDoc.GetOrCreateAsync(KeyStore.LinkedFromDocs, ListField, field => { (field as ListField<Document>).Data.push(linkDoc) });
-        linkDoc.Set(KeyStore.LinkedFromDocs, sourceDoc);
+            sourceDoc.GetOrCreateAsync(KeyStore.LinkedToDocs, ListField, field => { (field as ListField<Document>).Data.push(linkDoc) });
+            linkDoc.Set(KeyStore.LinkedToDocs, destDoc);
+            destDoc.GetOrCreateAsync(KeyStore.LinkedFromDocs, ListField, field => { (field as ListField<Document>).Data.push(linkDoc) });
+            linkDoc.Set(KeyStore.LinkedFromDocs, sourceDoc);
 
-        e.stopPropagation();
+            e.stopPropagation();
+        }
     }
 
     onDrop = (e: React.DragEvent) => {
-- 
cgit v1.2.3-70-g09d2

