aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/DocumentManager.ts2
-rw-r--r--src/client/util/LinkManager.ts2
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx9
-rw-r--r--src/client/views/linking/LinkEditor.tsx2
-rw-r--r--src/client/views/linking/LinkMenuGroup.tsx8
-rw-r--r--src/client/views/linking/LinkMenuItem.tsx23
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx59
8 files changed, 42 insertions, 65 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 420b29559..37d639a07 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -109,7 +109,7 @@ export class DocumentManager {
const pairs = DocumentManager.Instance.DocumentViews.reduce((pairs, dv) => {
const linksList = DocListCast(dv.props.Document.links);
pairs.push(...linksList.reduce((pairs, link) => {
- const linkToDoc = link && LinkManager.Instance.getOppositeAnchor(link, dv.props.Document);
+ const linkToDoc = link && LinkManager.getOppositeAnchor(link, dv.props.Document);
linkToDoc && DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => {
if (dv.props.Document.type !== DocumentType.LINK || dv.props.LayoutTemplateString !== docView1.props.LayoutTemplateString) {
pairs.push({ a: dv, b: docView1, l: link });
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 223f0e7ef..c7c45ec61 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -200,7 +200,7 @@ export class LinkManager {
// finds the opposite anchor of a given anchor in a link
//TODO This should probably return undefined if there isn't an opposite anchor
//TODO This should also await the return value of the anchor so we don't filter out promises
- public getOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc | undefined {
+ public static getOppositeAnchor(linkDoc: Doc, anchor: Doc): Doc | undefined {
const a1 = Cast(linkDoc.anchor1, Doc, null);
const a2 = Cast(linkDoc.anchor2, Doc, null);
if (Doc.AreProtosEqual(anchor, a1)) return a2;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index bed7e9735..d7a134eb3 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -292,7 +292,7 @@ export class CollectionDockingView extends CollectionSubView(doc => doc) {
setTimeout(() => {
CollectionDockingView.Instance._ignoreStateChange = JSON.stringify(CollectionDockingView.Instance._goldenLayout.toConfig());
this.stateChanged();
- this._flush!.end();
+ this._flush?.end();
this._flush = undefined;
}, 10);
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 8bc3cdf1b..79a540210 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -108,18 +108,19 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo
}
visibleY = (el: any) => {
- var rect = el.getBoundingClientRect(), top = rect.top, height = rect.height,
- el = el.parentNode;
+ let rect = el.getBoundingClientRect();
+ const top = rect.top, height = rect.height;
+ var el = el.parentNode;
do {
rect = el.getBoundingClientRect();
if (top <= rect.bottom === false && getComputedStyle(el).overflow === "hidden") return rect.bottom;
// Check if the element is out of view due to a container scrolling
if ((top + height) <= rect.top && getComputedStyle(el).overflow === "hidden") return rect.top;
el = el.parentNode;
- } while (el != document.body);
+ } while (el !== document.body);
// Check its within the document viewport
return top; //top <= document.documentElement.clientHeight && getComputedStyle(document.documentElement).overflow === "hidden";
- };
+ }
@computed get renderData() {
this._start;
diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx
index d6c3702d1..3713a1026 100644
--- a/src/client/views/linking/LinkEditor.tsx
+++ b/src/client/views/linking/LinkEditor.tsx
@@ -420,7 +420,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
}
render() {
- const destination = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
+ const destination = LinkManager.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc);
const groups = [this.props.linkDoc].map(groupDoc => {
return <LinkGroupEditor key={"gred-" + StrCast(groupDoc.linkRelationship)} linkDoc={this.props.linkDoc}
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index 8e09052a3..29e1d921c 100644
--- a/src/client/views/linking/LinkMenuGroup.tsx
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -48,7 +48,7 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
document.removeEventListener("pointermove", this.onLinkButtonMoved);
document.removeEventListener("pointerup", this.onLinkButtonUp);
- const targets = this.props.group.map(l => LinkManager.Instance.getOppositeAnchor(l, this.props.sourceDoc)).filter(d => d) as Doc[];
+ const targets = this.props.group.map(l => LinkManager.getOppositeAnchor(l, this.props.sourceDoc)).filter(d => d) as Doc[];
StartLinkTargetsDrag(this._drag.current, this.props.docView, e.x, e.y, this.props.sourceDoc, targets);
}
e.stopPropagation();
@@ -68,10 +68,10 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
render() {
const set = new Set<Doc>(this.props.group);
const groupItems = Array.from(set.keys()).map(linkDoc => {
- const destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc) ||
- LinkManager.Instance.getOppositeAnchor(linkDoc, Cast(linkDoc.anchor2, Doc, null).annotationOn === this.props.sourceDoc ? Cast(linkDoc.anchor2, Doc, null) : Cast(linkDoc.anchor1, Doc, null));
+ const destination = LinkManager.getOppositeAnchor(linkDoc, this.props.sourceDoc) ||
+ LinkManager.getOppositeAnchor(linkDoc, Cast(linkDoc.anchor2, Doc, null).annotationOn === this.props.sourceDoc ? Cast(linkDoc.anchor2, Doc, null) : Cast(linkDoc.anchor1, Doc, null));
if (destination && this.props.sourceDoc) {
- return <LinkMenuItem key={destination[Id] + this.props.sourceDoc[Id]}
+ return <LinkMenuItem key={linkDoc[Id]}
groupType={this.props.groupType}
addDocTab={this.props.addDocTab}
docView={this.props.docView}
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 17549e3cf..32fc407f6 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -33,7 +33,7 @@ interface LinkMenuItemProps {
// drag links and drop link targets (aliasing them if needed)
export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: DocumentView, downX: number, downY: number, sourceDoc: Doc, specificLinks?: Doc[]) {
- const draggedDocs = (specificLinks ? specificLinks : DocListCast(sourceDoc.links)).map(link => LinkManager.Instance.getOppositeAnchor(link, sourceDoc)).filter(l => l) as Doc[];
+ const draggedDocs = (specificLinks ? specificLinks : DocListCast(sourceDoc.links)).map(link => LinkManager.getOppositeAnchor(link, sourceDoc)).filter(l => l) as Doc[];
if (draggedDocs.length) {
const moddrag: Doc[] = [];
@@ -142,35 +142,34 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
DocumentLinksButton.EditLink = undefined;
LinkDocPreview.LinkInfo = undefined;
e.preventDefault();
- ContextMenu.Instance.addItem({ description: "Follow Default Link", event: () => this.followDefault(), icon: "arrow-right" });
+ ContextMenu.Instance.addItem({ description: "Follow Default Link", event: () => LinkMenuItem.followDefault(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc, this.props.addDocTab), icon: "arrow-right" });
ContextMenu.Instance.displayMenu(e.clientX, e.clientY);
}
@action.bound
- followDefault() {
+ public static followDefault(linkDoc: Doc, sourceDoc: Doc, destinationDoc: Doc, addDocTab: (doc: Doc, where: string) => void) {
DocumentLinksButton.EditLink = undefined;
LinkDocPreview.LinkInfo = undefined;
- const linkDoc = this.props.linkDoc;
- if (linkDoc.followLinkLocation === "openExternal" && this.props.destinationDoc.type === DocumentType.WEB) {
+ if (linkDoc.followLinkLocation === "openExternal" && destinationDoc.type === DocumentType.WEB) {
window.open(`${StrCast(linkDoc.annotationUri)}#annotations:${StrCast(linkDoc.annotationId)}`, '_blank');
return;
}
if (linkDoc.followLinkLocation && linkDoc.followLinkLocation !== "default") {
- const annotationOn = this.props.destinationDoc.annotationOn as Doc;
- this.props.addDocTab(annotationOn instanceof Doc ? annotationOn : this.props.destinationDoc, StrCast(linkDoc.followLinkLocation));
+ const annotationOn = destinationDoc.annotationOn as Doc;
+ addDocTab(annotationOn instanceof Doc ? annotationOn : destinationDoc, StrCast(linkDoc.followLinkLocation));
if (annotationOn) {
setTimeout(() => {
- const dv = DocumentManager.Instance.getFirstDocumentView(this.props.destinationDoc);
- dv?.props.focus(this.props.destinationDoc, false);
+ const dv = DocumentManager.Instance.getFirstDocumentView(destinationDoc);
+ dv?.props.focus(destinationDoc, false);
});
}
} else {
- DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.sourceDoc, doc => this.props.addDocTab(doc, "add:right"), false);
+ DocumentManager.Instance.FollowLink(linkDoc, this.props.sourceDoc, doc => addDocTab(doc, "add:right"), false);
}
- linkDoc.linksToAnnotation && Hypothesis.scrollToAnnotation(StrCast(this.props.linkDoc.annotationId), this.props.destinationDoc);
+ linkDoc.linksToAnnotation && Hypothesis.scrollToAnnotation(StrCast(linkDoc.annotationId), destinationDoc);
}
@undoBatch
@@ -250,7 +249,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
<div className="destination-icon-wrapper" >
<FontAwesomeIcon className="destination-icon" icon={destinationIcon} size="sm" /></div>
<p className="linkMenu-destination-title"
- onPointerDown={this.followDefault}>
+ onPointerDown={() => LinkMenuItem.followDefault(this.props.linkDoc, this.props.sourceDoc, this.props.destinationDoc, this.props.addDocTab)}>
{this.props.linkDoc.linksToAnnotation && Cast(this.props.destinationDoc.data, WebField)?.url.href === this.props.linkDoc.annotationUri ? "Annotation in" : ""} {title}
</p>
</div>
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index 6c71f08e7..1982cabab 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -1,28 +1,28 @@
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { Tooltip } from "@material-ui/core";
+import { action } from "mobx";
import { Mark, ResolvedPos } from "prosemirror-model";
import { EditorState, Plugin } from "prosemirror-state";
import { EditorView } from "prosemirror-view";
import * as ReactDOM from 'react-dom';
+import wiki from "wikijs";
import { Doc, DocCastAsync, Opt } from "../../../../fields/Doc";
import { Cast, FieldValue, NumCast, StrCast } from "../../../../fields/Types";
-import { emptyFunction, returnEmptyString, returnFalse, Utils, emptyPath, returnZero, returnOne, returnEmptyFilter, returnEmptyDoclist } from "../../../../Utils";
+import { emptyFunction, emptyPath, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnOne, Utils } from "../../../../Utils";
import { DocServer } from "../../../DocServer";
-import { DocumentManager } from "../../../util/DocumentManager";
-import { schema } from "./schema_rts";
+import { Docs } from "../../../documents/Documents";
+import { DocumentType } from "../../../documents/DocumentTypes";
+import { LinkManager } from "../../../util/LinkManager";
import { Transform } from "../../../util/Transform";
+import { undoBatch } from "../../../util/UndoManager";
+import { LinkMenuItem } from "../../linking/LinkMenuItem";
import { ContentFittingDocumentView } from "../ContentFittingDocumentView";
+import { DocumentLinksButton } from "../DocumentLinksButton";
+import { LinkDocPreview } from "../LinkDocPreview";
import { FormattedTextBox } from "./FormattedTextBox";
import './FormattedTextBoxComment.scss';
+import { schema } from "./schema_rts";
import React = require("react");
-import { Docs } from "../../../documents/Documents";
-import wiki from "wikijs";
-import { DocumentType } from "../../../documents/DocumentTypes";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action } from "mobx";
-import { LinkManager } from "../../../util/LinkManager";
-import { LinkDocPreview } from "../LinkDocPreview";
-import { DocumentLinksButton } from "../DocumentLinksButton";
-import { Tooltip } from "@material-ui/core";
-import { undoBatch } from "../../../util/UndoManager";
export let formattedTextBoxCommentPlugin = new Plugin({
view(editorView) { return new FormattedTextBoxComment(editorView); }
@@ -98,40 +98,18 @@ export class FormattedTextBoxComment {
const textBox = FormattedTextBoxComment.textBox;
const linkDoc = FormattedTextBoxComment.linkDoc;
if (linkDoc && !keep && textBox) {
- FormattedTextBoxComment.linkDoc = undefined;
if (linkDoc.author) {
if (FormattedTextBoxComment._deleteRef?.contains(e.target as any)) {
this.deleteLink();
- } else if (FormattedTextBoxComment._followRef && FormattedTextBoxComment._followRef.contains(e.target as any)) {
- if (linkDoc.type !== DocumentType.LINK) {
- textBox.props.addDocTab(linkDoc, e.ctrlKey ? "add" : "add:right");
- } else {
- const anchor = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(linkDoc.anchor1, Doc)), textBox.dataDoc) ?
- Cast(linkDoc.anchor2, Doc) : (Cast(linkDoc.anchor1, Doc))
- || linkDoc);
- const target = anchor?.annotationOn ? await DocCastAsync(anchor.annotationOn) : anchor;
-
- if (linkDoc.follow) {
- if (linkDoc.follow === "default") {
- DocumentManager.Instance.FollowLink(linkDoc, textBox.props.Document, doc => textBox.props.addDocTab(doc, "add:right"), false);
- } else if (linkDoc.follow === "Always open in right tab") {
- if (target) { textBox.props.addDocTab(target, "add:right"); }
- } else if (linkDoc.follow === "Always open in new tab") {
- if (target) { textBox.props.addDocTab(target, "add"); }
- }
- } else {
- DocumentManager.Instance.FollowLink(linkDoc, textBox.props.Document, doc => textBox.props.addDocTab(doc, "add:right"), false);
- }
- }
} else {
+ FormattedTextBoxComment.linkDoc = undefined;
if (linkDoc.type !== DocumentType.LINK) {
textBox.props.addDocTab(linkDoc, e.ctrlKey ? "add" : "add:right");
} else {
- DocumentManager.Instance.FollowLink(linkDoc, textBox.props.Document,
- (doc: Doc, followLinkLocation: string) => textBox.props.addDocTab(doc, e.ctrlKey ? "add" : followLinkLocation));
+ const target = LinkManager.getOppositeAnchor(linkDoc, textBox.dataDoc);
+ target && LinkMenuItem.followDefault(linkDoc, textBox.dataDoc, target, textBox.props.addDocTab);
}
}
-
}
} else if (textBox && (FormattedTextBoxComment.tooltipText as any).href) {
textBox.props.addDocTab(Docs.Create.WebDocument((FormattedTextBoxComment.tooltipText as any).href, { title: (FormattedTextBoxComment.tooltipText as any).href, _width: 200, _height: 400, useCors: true }), "add:right");
@@ -146,14 +124,13 @@ export class FormattedTextBoxComment {
}
@undoBatch
- @action
- deleteLink = () => {
+ deleteLink = action(() => {
FormattedTextBoxComment.linkDoc ? LinkManager.Instance.deleteLink(FormattedTextBoxComment.linkDoc) : null;
LinkDocPreview.LinkInfo = undefined;
DocumentLinksButton.EditLink = undefined;
//FormattedTextBoxComment.tooltipText = undefined;
FormattedTextBoxComment.Hide();
- }
+ });
public static Hide() {
FormattedTextBoxComment.textBox = undefined;