aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts4
-rw-r--r--src/client/util/DocumentManager.ts46
-rw-r--r--src/client/util/DragManager.ts47
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss38
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx88
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx148
-rw-r--r--src/client/views/nodes/DocumentView.tsx2
-rw-r--r--src/client/views/nodes/LinkMenu.scss15
-rw-r--r--src/client/views/nodes/LinkMenu.tsx18
-rw-r--r--src/client/views/nodes/LinkMenuGroup.tsx74
-rw-r--r--src/client/views/nodes/LinkMenuItem.tsx8
-rw-r--r--src/new_fields/Doc.ts16
12 files changed, 243 insertions, 261 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index df5c39562..7cef48b98 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -91,7 +91,9 @@ export namespace DocUtils {
// let protoSrc = source.proto ? source.proto : source;
// let protoTarg = target.proto ? target.proto : target;
export function MakeLink(source: Doc, target: Doc, targetContext?: Doc) {
- if (LinkManager.Instance.doesLinkExist(source, target)) return;
+ if (LinkManager.Instance.doesLinkExist(source, target)) {
+ console.log("LINK EXISTS"); return;
+ }
UndoManager.RunInBatch(() => {
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 325f4894d..c4cb6721a 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -85,51 +85,25 @@ export class DocumentManager {
@computed
public get LinkedDocumentViews() {
- // console.log("linked");
- // let docs = DocListCast(CurrentUserUtils.UserDocument.data);
- // docs.forEach(d => {
- // console.log("d", StrCast(d.title));
-
- // });
-
- // let d = Cast(CurrentUserUtils.UserDocument.activeWorkspace, Doc, new Doc);
- // console.log("DOC", StrCast(d.title));
-
-
-
- let linked = DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => {
- // console.log("FINDING LINKED DVs FOR", StrCast(dv.props.Document.title));
+ return DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => {
let linksList = LinkManager.Instance.findAllRelatedLinks(dv.props.Document);
+ // let linksList = DocListCast(dv.props.Document.linkedToDocs);
if (linksList && linksList.length) {
pairs.push(...linksList.reduce((pairs, link) => {
- // if (link) {
- let destination = LinkManager.Instance.findOppositeAnchor(link, dv.props.Document);
- // console.log("FINDING FOR", StrCast(dv.Document.title), StrCast(destination.title));
-
- if (destination) {
- let dvs = DocumentManager.Instance.getDocumentViews(destination);
- if (dvs.length > 0) {
- dvs.map(docView1 => {
- // console.log("PUSHING LINK BETWEEN", StrCast(dv.props.Document.title), StrCast(docView1.props.Document.title));
- // TODO: if any docviews are not in the same context, draw a proxy
- // let sameContent = dv.props.ContainingCollectionView === docView1.props.ContainingCollectionView;
- pairs.push({ anchor1View: dv, anchor2View: docView1, linkDoc: link });
- // console.log("PUSHED", StrCast(dv.props.Document.title), StrCast(docView1.Document.title));
- });
- } else {
- let dv = DocumentManager.Instance.getDocumentView(destination);
- dv ? console.log(StrCast(dv.props.Document.title)) : console.log("cant find");
- }
+ if (link) {
+ let linkToDoc = LinkManager.Instance.findOppositeAnchor(link, dv.props.Document);
+ // console.log("FOUND ", DocumentManager.Instance.getDocumentViews(linkToDoc).length, "DOCVIEWS FOR", StrCast(linkToDoc.title), "WITH SOURCE", StrCast(dv.props.Document.title));
+ DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 =>
+ pairs.push({ a: dv, b: docView1, l: link }));
}
- // }
return pairs;
- }, [] as { anchor1View: DocumentView, anchor2View: DocumentView, linkDoc: Doc }[]));
+ }, [] as { a: DocumentView, b: DocumentView, l: Doc }[]));
}
return pairs;
- }, [] as { anchor1View: DocumentView, anchor2View: DocumentView, linkDoc: Doc }[]);
- return linked;
+ }, [] as { a: DocumentView, b: DocumentView, l: Doc }[]);
}
+
@undoBatch
public jumpToDocument = async (docDelegate: Doc, forceDockFunc: boolean = false, dockFunc?: (doc: Doc) => void, linkPage?: number, docContext?: Doc): Promise<void> => {
let doc = Doc.GetProto(docDelegate);
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 11530ef09..2abcff4f7 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -48,12 +48,10 @@ export function SetupDrag(_reference: React.RefObject<HTMLElement>, docFunc: ()
export async function DragLinkAsDocument(dragEle: HTMLElement, x: number, y: number, linkDoc: Doc, sourceDoc: Doc) {
let draggeddoc = LinkManager.Instance.findOppositeAnchor(linkDoc, sourceDoc);
- // TODO: if not in same context then don't drag
-
let moddrag = await Cast(draggeddoc.annotationOn, Doc);
let dragData = new DragManager.DocumentDragData(moddrag ? [moddrag] : [draggeddoc]);
dragData.dropAction = "alias" as dropActionType;
- DragManager.StartDocumentDrag([dragEle], dragData, x, y, {
+ DragManager.StartLinkedDocumentDrag([dragEle], dragData, x, y, {
handlers: {
dragComplete: action(emptyFunction),
},
@@ -83,11 +81,21 @@ export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: n
if (doc) moddrag.push(doc);
}
let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs);
- dragData.dropAction = "alias" as dropActionType;
// dragData.moveDocument = (document, targetCollection, addDocument) => {
// return false;
// };
- DragManager.StartDocumentDrag([dragEle], dragData, x, y, {
+
+ // runInAction(() => StartDragFunctions.map(func => func()));
+ // (eles, dragData, downX, downY, options,
+ // (dropData: { [id: string]: any }) => {
+ // (dropData.droppedDocuments = dragData.userDropAction === "alias" || (!dragData.userDropAction && dragData.dropAction === "alias") ?
+ // dragData.draggedDocuments.map(d => Doc.MakeAlias(d)) :
+ // dragData.userDropAction === "copy" || (!dragData.userDropAction && dragData.dropAction === "copy") ?
+ // dragData.draggedDocuments.map(d => Doc.MakeCopy(d, true)) :
+ // dragData.draggedDocuments
+ // );
+ // });
+ DragManager.StartLinkedDocumentDrag([dragEle], dragData, x, y, {
handlers: {
dragComplete: action(emptyFunction),
},
@@ -215,6 +223,35 @@ export namespace DragManager {
});
}
+ export function StartLinkedDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) {
+
+ runInAction(() => StartDragFunctions.map(func => func()));
+ StartDrag(eles, dragData, downX, downY, options,
+ (dropData: { [id: string]: any }) => {
+ dropData.droppedDocuments = dragData.draggedDocuments.map(d => {
+ let dv = DocumentManager.Instance.getDocumentView(d);
+ // console.log("DRAG", StrCast(d.title));
+
+ if (dv) {
+ console.log("DRAG", StrCast(d.title), "has view");
+ if (dv.props.ContainingCollectionView === SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView) {
+ console.log("DRAG", StrCast(d.title), "same");
+ return d;
+ } else {
+ console.log("DRAG", StrCast(d.title), "diff");
+ return Doc.MakeAlias(d);
+ }
+ } else {
+ console.log("DRAG", StrCast(d.title), "has no view");
+ return Doc.MakeAlias(d);
+ }
+ // return (dv && dv.props.ContainingCollectionView !== SelectionManager.SelectedDocuments()[0].props.ContainingCollectionView) || !dv ?
+ // Doc.MakeAlias(d) : d;
+ });
+
+ });
+ }
+
export function StartAnnotationDrag(eles: HTMLElement[], dragData: AnnotationDragData, downX: number, downY: number, options?: DragOptions) {
StartDrag(eles, dragData, downX, downY, options);
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss
index d8d518147..239c2ce56 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.scss
@@ -1,22 +1,22 @@
-// .collectionfreeformlinkview-linkLine {
-// stroke: black;
-// transform: translate(10000px,10000px);
-// opacity: 0.5;
-// pointer-events: all;
-// }
-// .collectionfreeformlinkview-linkCircle {
-// stroke: rgb(0,0,0);
-// opacity: 0.5;
-// transform: translate(10000px,10000px);
-// pointer-events: all;
-// cursor: pointer;
-// }
-// .collectionfreeformlinkview-linkText {
-// stroke: rgb(0,0,0);
-// opacity: 0.5;
-// transform: translate(10000px,10000px);
-// pointer-events: all;
-// }
+.collectionfreeformlinkview-linkLine {
+ stroke: black;
+ transform: translate(10000px,10000px);
+ opacity: 0.5;
+ pointer-events: all;
+}
+.collectionfreeformlinkview-linkCircle {
+ stroke: rgb(0,0,0);
+ opacity: 0.5;
+ transform: translate(10000px,10000px);
+ pointer-events: all;
+ cursor: pointer;
+}
+.collectionfreeformlinkview-linkText {
+ stroke: rgb(0,0,0);
+ opacity: 0.5;
+ transform: translate(10000px,10000px);
+ pointer-events: all;
+}
.linkview-ele {
transform: translate(10000px,10000px);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 65d5ac474..5c7f080e0 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -5,70 +5,60 @@ import { InkingControl } from "../../InkingControl";
import "./CollectionFreeFormLinkView.scss";
import React = require("react");
import v5 = require("uuid/v5");
-import { DocumentView } from "../../nodes/DocumentView";
-import { Docs } from "../../../documents/Documents";
export interface CollectionFreeFormLinkViewProps {
- // anchor1: Doc;
- // anchor2: Doc;
- // LinkDocs: Doc[];
- // addDocument: (document: Doc, allowDuplicates?: boolean) => boolean;
- // removeDocument: (document: Doc) => boolean;
- // sameContext: boolean;
-
- // sourceView: DocumentView;
- // targetView: DocumentView;
- sourceView: Doc;
- targetView: Doc;
+ A: Doc;
+ B: Doc;
+ LinkDocs: Doc[];
+ addDocument: (document: Doc, allowDuplicates?: boolean) => boolean;
+ removeDocument: (document: Doc) => boolean;
}
@observer
export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFormLinkViewProps> {
- // onPointerDown = (e: React.PointerEvent) => {
- // if (e.button === 0 && !InkingControl.Instance.selectedTool) {
- // let a = this.props.A;
- // let b = this.props.B;
- // let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : a[WidthSym]() / 2);
- // let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : a[HeightSym]() / 2);
- // let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : b[WidthSym]() / 2);
- // let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : b[HeightSym]() / 2);
- // this.props.LinkDocs.map(l => {
- // let width = l[WidthSym]();
- // l.x = (x1 + x2) / 2 - width / 2;
- // l.y = (y1 + y2) / 2 + 10;
- // if (!this.props.removeDocument(l)) this.props.addDocument(l, false);
- // });
- // e.stopPropagation();
- // e.preventDefault();
- // }
- // }
-
-
+ onPointerDown = (e: React.PointerEvent) => {
+ if (e.button === 0 && !InkingControl.Instance.selectedTool) {
+ let a = this.props.A;
+ let b = this.props.B;
+ let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : a[WidthSym]() / 2);
+ let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : a[HeightSym]() / 2);
+ let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : b[WidthSym]() / 2);
+ let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : b[HeightSym]() / 2);
+ this.props.LinkDocs.map(l => {
+ let width = l[WidthSym]();
+ l.x = (x1 + x2) / 2 - width / 2;
+ l.y = (y1 + y2) / 2 + 10;
+ if (!this.props.removeDocument(l)) this.props.addDocument(l, false);
+ });
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }
render() {
- // let l = this.props.LinkDocs;
- // let a = this.props.A;
- // let b = this.props.B;
- let a1 = this.props.sourceView;
- let a2 = this.props.targetView;
- let x1 = NumCast(a1.x) + (BoolCast(a1.isMinimized, false) ? 5 : NumCast(a1.width) / NumCast(a1.zoomBasis, 1) / 2);
- let y1 = NumCast(a1.y) + (BoolCast(a1.isMinimized, false) ? 5 : NumCast(a1.height) / NumCast(a1.zoomBasis, 1) / 2);
-
- let x2 = NumCast(a2.x) + (BoolCast(a2.isMinimized, false) ? 5 : NumCast(a2.width) / NumCast(a2.zoomBasis, 1) / 2);
- let y2 = NumCast(a2.y) + (BoolCast(a2.isMinimized, false) ? 5 : NumCast(a2.height) / NumCast(a2.zoomBasis, 1) / 2);
-
+ let l = this.props.LinkDocs;
+ let a = this.props.A;
+ let b = this.props.B;
+ let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.width) / NumCast(a.zoomBasis, 1) / 2);
+ let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : NumCast(a.height) / NumCast(a.zoomBasis, 1) / 2);
+ let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.width) / NumCast(b.zoomBasis, 1) / 2);
+ let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : NumCast(b.height) / NumCast(b.zoomBasis, 1) / 2);
+ let text = "";
+ let first = this.props.LinkDocs[0];
+ if (this.props.LinkDocs.length === 1) text += first.title + (first.linkDescription ? "(" + StrCast(first.linkDescription) + ")" : "");
+ else text = "-multiple-";
+ text = "";
return (
<>
- <line className="linkview-line linkview-ele"
- // style={{ strokeWidth: `${2 * 1 / 2}` }}
+ <line key="linkLine" className="collectionfreeformlinkview-linkLine"
+ style={{ strokeWidth: `${2 * l.length / 2}` }}
x1={`${x1}`} y1={`${y1}`}
x2={`${x2}`} y2={`${y2}`} />
-
{/* <circle key="linkCircle" className="collectionfreeformlinkview-linkCircle"
cx={(x1 + x2) / 2} cy={(y1 + y2) / 2} r={8} onPointerDown={this.onPointerDown} /> */}
- {/* <text key="linkText" textAnchor="middle" className="collectionfreeformlinkview-linkText" x={`${(x1 + x2) / 2}`} y={`${(y1 + y2) / 2}`}>
+ <text key="linkText" textAnchor="middle" className="collectionfreeformlinkview-linkText" x={`${(x1 + x2) / 2}`} y={`${(y1 + y2) / 2}`}>
{text}
- </text> */}
+ </text>
</>
);
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index 9d2f8946b..854122592 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -1,4 +1,4 @@
-import { computed, IReactionDisposer, reaction, action } from "mobx";
+import { computed, IReactionDisposer, reaction } from "mobx";
import { observer } from "mobx-react";
import { Doc, DocListCast } from "../../../../new_fields/Doc";
import { Id } from "../../../../new_fields/FieldSymbols";
@@ -11,10 +11,6 @@ import { CollectionViewProps } from "../CollectionSubView";
import "./CollectionFreeFormLinksView.scss";
import { CollectionFreeFormLinkView } from "./CollectionFreeFormLinkView";
import React = require("react");
-import { CollectionFreeFormLinkWithProxyView } from "./CollectionFreeFormLinkWithProxyView";
-import { Docs } from "../../../documents/Documents";
-import { LinkButtonField } from "../../../../new_fields/LinkButtonField";
-import { LinkManager } from "../../../util/LinkManager";
@observer
export class CollectionFreeFormLinksView extends React.Component<CollectionViewProps> {
@@ -98,150 +94,42 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
@computed
get uniqueConnections() {
- // console.log("\n");
- let connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => {
- // console.log("CONNECTION BETWEEN", StrCast(connection.anchor1View.props.Document.title), StrCast(connection.anchor2View.props.Document.title));
- let srcViews = this.documentAnchors(connection.anchor1View);
- // srcViews.forEach(sv => {
- // console.log("DOCANCHORS SRC", StrCast(connection.anchor1View.Document.title), StrCast(sv.Document.title));
- // });
-
- let targetViews = this.documentAnchors(connection.anchor2View);
- // targetViews.forEach(sv => {
- // console.log("DOCANCHORS TARG", StrCast(connection.anchor2View.Document.title), StrCast(sv.Document.title));
- // });
-
- // console.log("lengths", srcViews.length, targetViews.length);
+ // DocumentManager.Instance.LinkedDocumentViews.forEach(d => {
+ // console.log("CONNECTION", StrCast(d.a.props.Document.title), StrCast(d.b.props.Document.title));
+ // });
- // srcViews.forEach(v => {
- // console.log("SOURCE VIEW", StrCast(v.props.Document.title));
- // });
- // targetViews.forEach(v => {
- // console.log("TARGET VIEW", StrCast(v.Document.title));
- // });
-
- let possiblePairs: { anchor1: Doc, anchor2: Doc }[] = [];
- // srcViews.map(sv => {
- // console.log("SOURCE VIEW", StrCast(sv.props.Document.title));
- // targetViews.map(tv => {
- // console.log("TARGET VIEW", StrCast(tv.props.Document.title));
- // // console.log("PUSHING PAIR", StrCast(sv.props.Document.title), StrCast(tv.props.Document.title));
- // possiblePairs.push({ anchor1: sv.props.Document, anchor2: tv.props.Document });
- // });
- // console.log("END\n");
- // });
- srcViews.forEach(sv => {
- // console.log("SOURCE VIEW", StrCast(sv.props.Document.title));
- targetViews.forEach(tv => {
- // console.log("TARGET VIEW", StrCast(tv.props.Document.title));
- // console.log("PUSHING PAIR", StrCast(sv.props.Document.title), StrCast(tv.props.Document.title));
- possiblePairs.push({ anchor1: sv.props.Document, anchor2: tv.props.Document });
- });
- // console.log("END\n");
- });
- // console.log("POSSIBLE PAIRS LENGTH", possiblePairs.length);
+ let connections = DocumentManager.Instance.LinkedDocumentViews.reduce((drawnPairs, connection) => {
+ let srcViews = this.documentAnchors(connection.a);
+ let targetViews = this.documentAnchors(connection.b);
+ let possiblePairs: { a: Doc, b: Doc, }[] = [];
+ srcViews.map(sv => targetViews.map(tv => possiblePairs.push({ a: sv.props.Document, b: tv.props.Document })));
possiblePairs.map(possiblePair => {
- // console.log("POSSIBLEPAIR", StrCast(possiblePair.anchor1.title), StrCast(possiblePair.anchor2.title));
if (!drawnPairs.reduce((found, drawnPair) => {
- let match1 = (Doc.AreProtosEqual(possiblePair.anchor1, drawnPair.anchor1) && Doc.AreProtosEqual(possiblePair.anchor2, drawnPair.anchor2));
- let match2 = (Doc.AreProtosEqual(possiblePair.anchor1, drawnPair.anchor2) && Doc.AreProtosEqual(possiblePair.anchor2, drawnPair.anchor1));
+ let match1 = (Doc.AreProtosEqual(possiblePair.a, drawnPair.a) && Doc.AreProtosEqual(possiblePair.b, drawnPair.b));
+ let match2 = (Doc.AreProtosEqual(possiblePair.a, drawnPair.b) && Doc.AreProtosEqual(possiblePair.b, drawnPair.a));
let match = match1 || match2;
- if (match && !drawnPair.linkDocs.reduce((found, link) => found || link[Id] === connection.linkDoc[Id], false)) {
- drawnPair.linkDocs.push(connection.linkDoc);
+ if (match && !drawnPair.l.reduce((found, link) => found || link[Id] === connection.l[Id], false)) {
+ drawnPair.l.push(connection.l);
}
return match || found;
}, false)) {
- drawnPairs.push({ anchor1: possiblePair.anchor1, anchor2: possiblePair.anchor2, linkDocs: [connection.linkDoc] });
+ drawnPairs.push({ a: possiblePair.a, b: possiblePair.b, l: [connection.l] });
}
});
return drawnPairs;
- }, [] as { anchor1: Doc, anchor2: Doc, linkDocs: Doc[] }[]);
+ }, [] as { a: Doc, b: Doc, l: Doc[] }[]);
return connections.map(c => {
- let x = c.linkDocs.reduce((p, l) => p + l[Id], "");
- return <CollectionFreeFormLinkView key={x} sourceView={c.anchor1} targetView={c.anchor2} />;
+ let x = c.l.reduce((p, l) => p + l[Id], "");
+ return <CollectionFreeFormLinkView key={x} A={c.a} B={c.b} LinkDocs={c.l}
+ removeDocument={this.props.removeDocument} addDocument={this.props.addDocument} />;
});
}
- // findUniquePairs = (): JSX.Element[] => {
- // let connections = DocumentManager.Instance.LinkedDocumentViews;
-
- // // console.log("CONNECTIONS");
- // // connections.forEach(c => console.log(StrCast(c.anchor1View.Document.title), StrCast(c.anchor2View.Document.title)));
-
- // let unique: Set<{ sourceView: DocumentView, targetView: DocumentView, linkDoc: Doc }> = new Set();
- // connections.forEach(c => {
-
- // // let match1Index = unique.findIndex(u => (c.anchor1View === u.sourceView) && (c.anchor2View === u.targetView));
- // // let match2Index = unique.findIndex(u => (c.anchor1View === u.targetView) && (c.anchor2View === u.sourceView));
- // let match1 = unique.has({ sourceView: c.anchor1View, targetView: c.anchor2View, linkDoc: c.linkDoc });
- // let match2 = unique.has({ sourceView: c.anchor2View, targetView: c.anchor1View, linkDoc: c.linkDoc });
- // let sameContext = c.anchor1View.props.ContainingCollectionView === c.anchor2View.props.ContainingCollectionView;
-
- // // console.log("CONNECTION", StrCast(c.anchor1View.props.Document.title), StrCast(c.anchor2View.props.Document.title), match1, match2);
-
-
- // // if in same context, push if docview pair does not already exist
- // // else push both directions of pair
- // if (sameContext) {
- // if (!(match1 || match2)) unique.add({ sourceView: c.anchor1View, targetView: c.anchor2View, linkDoc: c.linkDoc });
- // } else {
- // unique.add({ sourceView: c.anchor1View, targetView: c.anchor2View, linkDoc: c.linkDoc });
- // unique.add({ sourceView: c.anchor2View, targetView: c.anchor1View, linkDoc: c.linkDoc });
- // }
- // });
-
- // let uniqueList: JSX.Element[] = [];
- // unique.forEach(u => {
- // // TODO: make better key
- // let key = StrCast(u.sourceView.Document[Id]) + "-link-" + StrCast(u.targetView.Document[Id]) + "-" + Date.now() + Math.random();
- // let sourceIn = u.sourceView.props.ContainingCollectionView ? u.sourceView.props.ContainingCollectionView.props.Document === this.props.Document : false;
- // let targetIn = u.targetView.props.ContainingCollectionView ? u.targetView.props.ContainingCollectionView.props.Document === this.props.Document : false;
- // let sameContext = u.sourceView.props.ContainingCollectionView === u.targetView.props.ContainingCollectionView;
- // let inContainer = sameContext ? sourceIn || targetIn : sourceIn;
-
- // if (inContainer) {
- // // let alias = Doc.MakeAlias(proxy);
- // if (sameContext) {
- // uniqueList.push(<CollectionFreeFormLinkView key={key} sourceView={u.sourceView} targetView={u.targetView} />);
- // } else {
- // let proxy = LinkManager.Instance.findLinkProxy(StrCast(u.sourceView.props.Document[Id]), StrCast(u.targetView.props.Document[Id]));
- // if (!proxy) {
- // proxy = Docs.LinkButtonDocument(
- // { sourceViewId: StrCast(u.sourceView.props.Document[Id]), targetViewId: StrCast(u.targetView.props.Document[Id]) },
- // { width: 200, height: 100, borderRounding: 0 });
- // let proxy1Proto = Doc.GetProto(proxy);
- // proxy1Proto.sourceViewId = StrCast(u.sourceView.props.Document[Id]);
- // proxy1Proto.targetViewId = StrCast(u.targetView.props.Document[Id]);
- // proxy1Proto.isLinkButton = true;
-
- // // LinkManager.Instance.linkProxies.push(proxy);
- // LinkManager.Instance.addLinkProxy(proxy);
- // }
- // uniqueList.push(<CollectionFreeFormLinkWithProxyView key={key} sourceView={u.sourceView} targetView={u.targetView} proxyDoc={proxy} />);
-
- // // let proxy = LinkManager.Instance.findLinkProxy(StrCast(u.sourceView.props.Document[Id]), StrCast(u.targetView.props.Document[Id]));
- // // if (proxy) {
- // // this.props.addDocument(proxy, false);
- // // uniqueList.push(<CollectionFreeFormLinkWithProxyView key={key} sourceView={u.sourceView} targetView={u.targetView} />);
- // // }
- // // let proxyKey = Doc.AreProtosEqual(u.sourceView.Document, Cast(u.linkDoc.anchor1, Doc, new Doc)) ? "proxy1" : "proxy2";
- // // let proxy = Cast(u.linkDoc[proxyKey], Doc, new Doc);
- // // this.props.addDocument(proxy, false);
-
- // // uniqueList.push(<CollectionFreeFormLinkWithProxyView key={key} sourceView={u.sourceView} targetView={u.targetView}
- // // proxyDoc={proxy} addDocTab={this.props.addDocTab} />);
- // }
- // }
- // });
- // return uniqueList;
- // }
-
render() {
return (
<div className="collectionfreeformlinksview-container">
<svg className="collectionfreeformlinksview-svgCanvas">
{this.uniqueConnections}
- {/* {this.findUniquePairs()} */}
</svg>
{this.props.children}
</div>
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index dbbae2d59..1fc2cf770 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -161,7 +161,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
this._animateToIconDisposer = reaction(() => this.props.Document.isIconAnimating, (values) =>
(values instanceof List) && this.animateBetweenIcon(values, values[2], values[3] ? true : false)
, { fireImmediately: true });
+ // console.log("CREATED NEW DOC VIEW", StrCast(this.props.Document.title), DocumentManager.Instance.DocumentViews.length);
DocumentManager.Instance.DocumentViews.push(this);
+ // console.log("ADDED TO DOC MAN", StrCast(this.props.Document.title), DocumentManager.Instance.DocumentViews.length);
}
animateBetweenIcon = (iconPos: number[], startTime: number, maximizing: boolean) => {
diff --git a/src/client/views/nodes/LinkMenu.scss b/src/client/views/nodes/LinkMenu.scss
index d2e411c3d..c01ed23c4 100644
--- a/src/client/views/nodes/LinkMenu.scss
+++ b/src/client/views/nodes/LinkMenu.scss
@@ -18,8 +18,19 @@
}
.linkMenu-group-name {
- border-bottom: 0.5px solid lightgray;
- margin-bottom: 4px;
+ padding: 4px 6px;
+ line-height: 12px;
+ border-radius: 5px;
+ margin-bottom: 2px;
+
+ &:hover {
+ background-color: lightgray;
+ }
+ }
+
+ .linkMenu-group-wrapper {
+ border-top: 0.5px solid lightgray;
+ padding-top: 4px;
}
}
diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx
index 8aca130a5..f96c7d2e4 100644
--- a/src/client/views/nodes/LinkMenu.tsx
+++ b/src/client/views/nodes/LinkMenu.tsx
@@ -8,6 +8,9 @@ import React = require("react");
import { Doc, DocListCast } from "../../../new_fields/Doc";
import { Id } from "../../../new_fields/FieldSymbols";
import { LinkManager } from "../../util/LinkManager";
+import { DragLinksAsDocuments, DragManager } from "../../util/DragManager";
+import { emptyFunction } from "../../../Utils";
+import { LinkMenuGroup } from "./LinkMenuGroup";
interface Props {
docView: DocumentView;
@@ -19,24 +22,11 @@ export class LinkMenu extends React.Component<Props> {
@observable private _editingLink?: Doc;
- renderGroup = (group: Doc[], groupType: string): Array<JSX.Element> => {
- let source = this.props.docView.Document;
- return group.map(linkDoc => {
- let destination = LinkManager.Instance.findOppositeAnchor(linkDoc, source);
- return <LinkMenuItem key={destination[Id] + source[Id]} groupType={groupType} linkDoc={linkDoc} sourceDoc={source} destinationDoc={destination} showEditor={action(() => this._editingLink = linkDoc)} />;
- });
- }
-
renderAllGroups = (groups: Map<string, Array<Doc>>): Array<JSX.Element> => {
let linkItems: Array<JSX.Element> = [];
groups.forEach((group, groupType) => {
linkItems.push(
- <div key={groupType} className="linkMenu-group">
- <p className="linkMenu-group-name">{groupType}:</p>
- <div className="linkMenu-group-wrapper">
- {this.renderGroup(group, groupType)}
- </div>
- </div>
+ <LinkMenuGroup key={groupType} sourceDoc={this.props.docView.props.Document} group={group} groupType={groupType} showEditor={action((linkDoc: Doc) => this._editingLink = linkDoc)} />
);
});
diff --git a/src/client/views/nodes/LinkMenuGroup.tsx b/src/client/views/nodes/LinkMenuGroup.tsx
new file mode 100644
index 000000000..229143d99
--- /dev/null
+++ b/src/client/views/nodes/LinkMenuGroup.tsx
@@ -0,0 +1,74 @@
+import { action, observable } from "mobx";
+import { observer } from "mobx-react";
+import { DocumentView } from "./DocumentView";
+import { LinkMenuItem } from "./LinkMenuItem";
+import { LinkEditor } from "./LinkEditor";
+import './LinkMenu.scss';
+import React = require("react");
+import { Doc, DocListCast } from "../../../new_fields/Doc";
+import { Id } from "../../../new_fields/FieldSymbols";
+import { LinkManager } from "../../util/LinkManager";
+import { DragLinksAsDocuments, DragManager } from "../../util/DragManager";
+import { emptyFunction } from "../../../Utils";
+
+interface LinkMenuGroupProps {
+ sourceDoc: Doc;
+ group: Doc[];
+ groupType: string;
+ showEditor: (linkDoc: Doc) => void;
+}
+
+@observer
+export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
+
+ private _drag = React.createRef<HTMLDivElement>();
+
+ onLinkButtonDown = (e: React.PointerEvent): void => {
+ e.stopPropagation();
+ document.removeEventListener("pointermove", this.onLinkButtonMoved);
+ document.addEventListener("pointermove", this.onLinkButtonMoved);
+ document.removeEventListener("pointerup", this.onLinkButtonUp);
+ document.addEventListener("pointerup", this.onLinkButtonUp);
+ }
+
+ onLinkButtonUp = (e: PointerEvent): void => {
+ document.removeEventListener("pointermove", this.onLinkButtonMoved);
+ document.removeEventListener("pointerup", this.onLinkButtonUp);
+ e.stopPropagation();
+ }
+
+ onLinkButtonMoved = async (e: PointerEvent) => {
+ if (this._drag.current !== null && (e.movementX > 1 || e.movementY > 1)) {
+ document.removeEventListener("pointermove", this.onLinkButtonMoved);
+ document.removeEventListener("pointerup", this.onLinkButtonUp);
+
+ let draggedDocs = this.props.group.map(linkDoc => LinkManager.Instance.findOppositeAnchor(linkDoc, this.props.sourceDoc));
+ let dragData = new DragManager.DocumentDragData(draggedDocs);
+
+ DragManager.StartLinkedDocumentDrag([this._drag.current], dragData, e.x, e.y, {
+ handlers: {
+ dragComplete: action(emptyFunction),
+ },
+ hideSource: false
+ });
+ }
+ e.stopPropagation();
+ }
+
+ render() {
+ let groupItems = this.props.group.map(linkDoc => {
+ let destination = LinkManager.Instance.findOppositeAnchor(linkDoc, this.props.sourceDoc);
+ return <LinkMenuItem key={destination[Id] + this.props.sourceDoc[Id]} groupType={this.props.groupType}
+ linkDoc={linkDoc} sourceDoc={this.props.sourceDoc} destinationDoc={destination} showEditor={this.props.showEditor} />;
+ });
+
+ return (
+ <div className="linkMenu-group">
+ <p className="linkMenu-group-name" ref={this._drag} onPointerDown={this.onLinkButtonDown} >{this.props.groupType}:</p>
+ <div className="linkMenu-group-wrapper">
+ {groupItems}
+ </div>
+ </div>
+ )
+ }
+} \ No newline at end of file
diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx
index 1ef4690b0..42ef353b7 100644
--- a/src/client/views/nodes/LinkMenuItem.tsx
+++ b/src/client/views/nodes/LinkMenuItem.tsx
@@ -21,7 +21,7 @@ interface LinkMenuItemProps {
linkDoc: Doc;
sourceDoc: Doc;
destinationDoc: Doc;
- showEditor: () => void;
+ showEditor: (linkDoc: Doc) => void;
}
@observer
@@ -42,7 +42,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
onEdit = (e: React.PointerEvent): void => {
e.stopPropagation();
- this.props.showEditor();
+ this.props.showEditor(this.props.linkDoc);
}
renderMetadata = (): JSX.Element => {
@@ -95,12 +95,12 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
<div className="linkMenu-item">
<div className={canExpand ? "linkMenu-item-content expand-three" : "linkMenu-item-content expand-two"}>
<div className="link-name">
- <p>{StrCast(this.props.destinationDoc.title)}</p>
+ <p ref={this._drag} onPointerDown={this.onLinkButtonDown}>{StrCast(this.props.destinationDoc.title)}</p>
<div className="linkMenu-item-buttons">
{canExpand ? <div title="Show more" className="button" onPointerDown={() => this.toggleShowMore()}>
<FontAwesomeIcon className="fa-icon" icon={this._showMore ? "chevron-up" : "chevron-down"} size="sm" /></div> : <></>}
<div title="Edit link" className="button" onPointerDown={this.onEdit}><FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div>
- <div title="Follow link" className="button" ref={this._drag} onPointerDown={this.onLinkButtonDown} onPointerUp={this.onFollowLink}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div>
+ <div title="Follow link" className="button" onPointerDown={this.onFollowLink}><FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div>
</div>
</div>
{this._showMore ? this.renderMetadata() : <></>}
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 1b0ff812f..5ce47fc2f 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -3,11 +3,13 @@ import { serializable, primitive, map, alias, list } from "serializr";
import { autoObject, SerializationHelper, Deserializable } from "../client/util/SerializationHelper";
import { DocServer } from "../client/DocServer";
import { setter, getter, getField, updateFunction, deleteProperty } from "./util";
-import { Cast, ToConstructor, PromiseValue, FieldValue, NumCast } from "./Types";
+import { Cast, ToConstructor, PromiseValue, FieldValue, NumCast, StrCast } from "./Types";
import { listSpec } from "./Schema";
import { ObjectField } from "./ObjectField";
import { RefField, FieldId } from "./RefField";
import { ToScriptString, SelfProxy, Parent, OnUpdate, Self, HandleUpdate, Update, Id } from "./FieldSymbols";
+import { LinkManager } from "../client/util/LinkManager";
+import { DocUtils } from "../client/documents/Documents";
export namespace Field {
export function toScriptString(field: Field): string {
@@ -247,6 +249,18 @@ export namespace Doc {
}
}
});
+ console.log("COPY", StrCast(doc.title));
+ let links = LinkManager.Instance.findAllRelatedLinks(doc);
+ links.forEach(linkDoc => {
+ let opp = LinkManager.Instance.findOppositeAnchor(linkDoc, doc);
+ console.log("OPP", StrCast(opp.title));
+ DocUtils.MakeLink(opp, copy);
+ });
+
+ LinkManager.Instance.allLinks.forEach(l => {
+ console.log("LINK", StrCast(Cast(l.anchor1, Doc, new Doc).title), StrCast(Cast(l.anchor2, Doc, new Doc).title));
+ });
+
return copy;
}