diff options
| author | Melissa Zhang <mzhang19096@gmail.com> | 2020-09-30 22:01:44 -0600 |
|---|---|---|
| committer | Melissa Zhang <mzhang19096@gmail.com> | 2020-09-30 22:01:44 -0600 |
| commit | 09aab9558a26a2d7c8e3d485aca578960af72821 (patch) | |
| tree | b53bdc6f2fcb269b74a097f56bfeec248e7f918b /src/client/views/linking | |
| parent | bd827b97c719abeadf243ba4f8b2ba417badb65b (diff) | |
| parent | 852ddf70b7ed3d027eb5cb8415df4df77b8652a6 (diff) | |
pull from master
Diffstat (limited to 'src/client/views/linking')
| -rw-r--r-- | src/client/views/linking/LinkEditor.tsx | 37 | ||||
| -rw-r--r-- | src/client/views/linking/LinkMenu.scss | 2 | ||||
| -rw-r--r-- | src/client/views/linking/LinkMenu.tsx | 23 | ||||
| -rw-r--r-- | src/client/views/linking/LinkMenuGroup.tsx | 11 | ||||
| -rw-r--r-- | src/client/views/linking/LinkMenuItem.tsx | 55 |
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> |
