aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/linking
diff options
context:
space:
mode:
authorMelissa Zhang <mzhang19096@gmail.com>2020-09-30 22:01:44 -0600
committerMelissa Zhang <mzhang19096@gmail.com>2020-09-30 22:01:44 -0600
commit09aab9558a26a2d7c8e3d485aca578960af72821 (patch)
treeb53bdc6f2fcb269b74a097f56bfeec248e7f918b /src/client/views/linking
parentbd827b97c719abeadf243ba4f8b2ba417badb65b (diff)
parent852ddf70b7ed3d027eb5cb8415df4df77b8652a6 (diff)
pull from master
Diffstat (limited to 'src/client/views/linking')
-rw-r--r--src/client/views/linking/LinkEditor.tsx37
-rw-r--r--src/client/views/linking/LinkMenu.scss2
-rw-r--r--src/client/views/linking/LinkMenu.tsx23
-rw-r--r--src/client/views/linking/LinkMenuGroup.tsx11
-rw-r--r--src/client/views/linking/LinkMenuItem.tsx55
5 files changed, 66 insertions, 62 deletions
diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx
index ed64bde32..3713a1026 100644
--- a/src/client/views/linking/LinkEditor.tsx
+++ b/src/client/views/linking/LinkEditor.tsx
@@ -1,5 +1,3 @@
-import { library } from "@fortawesome/fontawesome-svg-core";
-import { faArrowLeft, faCog, faEllipsisV, faExchangeAlt, faPlus, faTable, faTimes, faTrash } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Tooltip } from "@material-ui/core";
import { action, computed, observable } from "mobx";
@@ -12,9 +10,6 @@ import { undoBatch } from "../../util/UndoManager";
import './LinkEditor.scss';
import React = require("react");
-library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus);
-
-
interface GroupTypesDropdownProps {
groupType: string;
setGroupType: (group: string) => void;
@@ -369,7 +364,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
<div className="linkEditor-followingDropdown-dropdown">
<div className="linkEditor-followingDropdown-header"
onPointerDown={this.changeDropdown}>
- {StrCast(this.props.linkDoc.followLinkLocation, "Default")}
+ {StrCast(this.props.linkDoc.followLinkLocation, "default")}
<FontAwesomeIcon className="linkEditor-followingDropdown-icon"
icon={this.openDropdown ? "chevron-up" : "chevron-down"}
size={"lg"} />
@@ -377,17 +372,37 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
<div className="linkEditor-followingDropdown-optionsList"
style={{ display: this.openDropdown ? "" : "none" }}>
<div className="linkEditor-followingDropdown-option"
- onPointerDown={() => this.changeFollowBehavior("Default")}>
+ onPointerDown={() => this.changeFollowBehavior("default")}>
Default
</div>
<div className="linkEditor-followingDropdown-option"
- onPointerDown={() => this.changeFollowBehavior("onRight")}>
- Always open in a new pane
+ onPointerDown={() => this.changeFollowBehavior("add:left")}>
+ Always open in new left pane
+ </div>
+ <div className="linkEditor-followingDropdown-option"
+ onPointerDown={() => this.changeFollowBehavior("add:right")}>
+ Always open in new right pane
+ </div>
+ <div className="linkEditor-followingDropdown-option"
+ onPointerDown={() => this.changeFollowBehavior("replace:right")}>
+ Always replace right tab
</div>
<div className="linkEditor-followingDropdown-option"
- onPointerDown={() => this.changeFollowBehavior("inTab")}>
+ onPointerDown={() => this.changeFollowBehavior("replace:left")}>
+ Always replace left tab
+ </div>
+ <div className="linkEditor-followingDropdown-option"
+ onPointerDown={() => this.changeFollowBehavior("fullScreen")}>
+ Always open full screen
+ </div>
+ <div className="linkEditor-followingDropdown-option"
+ onPointerDown={() => this.changeFollowBehavior("add")}>
Always open in a new tab
</div>
+ <div className="linkEditor-followingDropdown-option"
+ onPointerDown={() => this.changeFollowBehavior("replace")}>
+ Replace Tab
+ </div>
{this.props.linkDoc.linksToAnnotation ?
<div className="linkEditor-followingDropdown-option"
onPointerDown={() => this.changeFollowBehavior("openExternal")}>
@@ -405,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/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss
index 4dc25031d..0e03b46db 100644
--- a/src/client/views/linking/LinkMenu.scss
+++ b/src/client/views/linking/LinkMenu.scss
@@ -4,8 +4,6 @@
width: auto;
height: auto;
position: absolute;
- top: 0;
- left: 0;
z-index: 999;
.linkMenu-list {
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
index 8ecde959f..3b4912d3d 100644
--- a/src/client/views/linking/LinkMenu.tsx
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -1,18 +1,14 @@
-import { action, observable, computed } from "mobx";
+import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
-import { DocumentView } from "../nodes/DocumentView";
-import { LinkEditor } from "./LinkEditor";
-import './LinkMenu.scss';
-import React = require("react");
import { Doc } from "../../../fields/Doc";
import { LinkManager } from "../../util/LinkManager";
-import { LinkMenuGroup } from "./LinkMenuGroup";
-import { faTrash } from '@fortawesome/free-solid-svg-icons';
-import { library } from "@fortawesome/fontawesome-svg-core";
import { DocumentLinksButton } from "../nodes/DocumentLinksButton";
+import { DocumentView } from "../nodes/DocumentView";
import { LinkDocPreview } from "../nodes/LinkDocPreview";
-
-library.add(faTrash);
+import { LinkEditor } from "./LinkEditor";
+import './LinkMenu.scss';
+import { LinkMenuGroup } from "./LinkMenuGroup";
+import React = require("react");
interface Props {
docView: DocumentView;
@@ -93,15 +89,14 @@ export class LinkMenu extends React.Component<Props> {
}
render() {
- console.log("computed", this.position.x, this.position.b);
const sourceDoc = this.props.docView.props.Document;
const groups: Map<string, Doc[]> = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc);
- return <div className="linkMenu" ref={this._linkMenuRef} >
+ return <div className="linkMenu" style={{ left: this.position.x, top: this.props.docView.topMost ? undefined : this.position.b + 15, bottom: this.props.docView.topMost ? 20 : undefined }} ref={this._linkMenuRef} >
{!this._editingLink ?
- <div className="linkMenu-list" style={{ left: this.position.x, top: this.position.b + 15 }}>
+ <div className="linkMenu-list" >
{this.renderAllGroups(groups)}
</div> :
- <div className="linkMenu-listEditor" style={{ left: this.position.x, top: this.position.b + 15 }}>
+ <div className="linkMenu-listEditor">
<LinkEditor sourceDoc={this.props.docView.props.Document} linkDoc={this._editingLink}
showLinks={action(() => this._editingLink = undefined)} />
</div>
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index 2ae87ac13..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();
@@ -66,11 +66,12 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
}
render() {
- const groupItems = this.props.group.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 set = new Set<Doc>(this.props.group);
+ const groupItems = Array.from(set.keys()).map(linkDoc => {
+ 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 21c666a4d..3a8d41fef 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -1,27 +1,23 @@
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { faArrowRight, faChevronDown, faChevronUp, faEdit, faEye, faTimes, faPencilAlt, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon, FontAwesomeIconProps } from '@fortawesome/react-fontawesome';
+import { Tooltip } from '@material-ui/core';
import { action, observable, runInAction } from 'mobx';
import { observer } from "mobx-react";
-import { Doc, DocListCast, Opt } from '../../../fields/Doc';
+import { Doc, DocListCast } from '../../../fields/Doc';
import { Cast, StrCast } from '../../../fields/Types';
+import { WebField } from '../../../fields/URLField';
+import { emptyFunction, setupMoveUpEvents } from '../../../Utils';
+import { DocumentType } from '../../documents/DocumentTypes';
+import { DocumentManager } from '../../util/DocumentManager';
import { DragManager } from '../../util/DragManager';
+import { Hypothesis } from '../../util/HypothesisUtils';
import { LinkManager } from '../../util/LinkManager';
+import { undoBatch } from '../../util/UndoManager';
import { ContextMenu } from '../ContextMenu';
-import './LinkMenuItem.scss';
-import React = require("react");
-import { DocumentManager } from '../../util/DocumentManager';
-import { setupMoveUpEvents, emptyFunction, Utils, simulateMouseClick } from '../../../Utils';
-import { DocumentView } from '../nodes/DocumentView';
import { DocumentLinksButton } from '../nodes/DocumentLinksButton';
+import { DocumentView } from '../nodes/DocumentView';
import { LinkDocPreview } from '../nodes/LinkDocPreview';
-import { Hypothesis } from '../../util/HypothesisUtils';
-import { Id } from '../../../fields/FieldSymbols';
-import { Tooltip } from '@material-ui/core';
-import { DocumentType } from '../../documents/DocumentTypes';
-import { undoBatch } from '../../util/UndoManager';
-import { WebField } from '../../../fields/URLField';
-library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp, faPencilAlt, faEyeSlash);
+import './LinkMenuItem.scss';
+import React = require("react");
interface LinkMenuItemProps {
@@ -37,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[] = [];
@@ -146,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() {
+
+ @action
+ 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));
+ if (linkDoc.followLinkLocation && linkDoc.followLinkLocation !== "default") {
+ 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, "onRight"), false);
+ DocumentManager.Instance.FollowLink(linkDoc, sourceDoc, addDocTab, false);
}
- linkDoc.linksToAnnotation && Hypothesis.scrollToAnnotation(StrCast(this.props.linkDoc.annotationId), this.props.destinationDoc);
+ linkDoc.linksToAnnotation && Hypothesis.scrollToAnnotation(StrCast(linkDoc.annotationId), destinationDoc);
}
@undoBatch
@@ -254,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={() => DocumentView.followLinkClick(this.props.linkDoc, this.props.sourceDoc, this.props.docView.props, false, false)}>
{this.props.linkDoc.linksToAnnotation && Cast(this.props.destinationDoc.data, WebField)?.url.href === this.props.linkDoc.annotationUri ? "Annotation in" : ""} {title}
</p>
</div>