diff options
Diffstat (limited to 'src/client/views')
| -rw-r--r-- | src/client/views/collections/CollectionLinearView.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/linking/LinkMenuItem.tsx | 11 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentLinksButton.tsx | 80 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 1 |
4 files changed, 86 insertions, 8 deletions
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx index 407524353..cd6e60de6 100644 --- a/src/client/views/collections/CollectionLinearView.tsx +++ b/src/client/views/collections/CollectionLinearView.tsx @@ -176,7 +176,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { }} onPointerDown={e => e.stopPropagation()} > <span className="bottomPopup-text" > - Creating link from: {DocumentLinksButton.StartLink.title} + Creating link from: {DocumentLinksButton.AnnotationId ? "Annotation in" : ""} {DocumentLinksButton.StartLink.title} </span> <Tooltip title={<><div className="dash-tooltip">{LinkDescriptionPopup.showDescriptions ? "Turn off description pop-up" : diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index d1c839c3b..cae90cd0c 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -11,10 +11,12 @@ import { ContextMenu } from '../ContextMenu'; import './LinkMenuItem.scss'; import React = require("react"); import { DocumentManager } from '../../util/DocumentManager'; -import { setupMoveUpEvents, emptyFunction } from '../../../Utils'; +import { setupMoveUpEvents, emptyFunction, Utils } from '../../../Utils'; import { DocumentView } from '../nodes/DocumentView'; import { DocumentLinksButton } from '../nodes/DocumentLinksButton'; import { LinkDocPreview } from '../nodes/LinkDocPreview'; +import { Hypothesis } from '../../apis/hypothesis/HypothesisApiUtils'; +import { Id } from '../../../fields/FieldSymbols'; import { Tooltip } from '@material-ui/core'; import { DocumentType } from '../../documents/DocumentTypes'; import { undoBatch } from '../../util/UndoManager'; @@ -152,16 +154,21 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { DocumentLinksButton.EditLink = undefined; LinkDocPreview.LinkInfo = undefined; + // this.props.linkDoc.linksToAnnotation && (Doc.GetProto(this.props.destinationDoc).data = new WebField(StrCast(this.props.linkDoc.annotationUrl))); // if destination is a Hypothes.is annotation, redirect website to the annotation's URL to scroll to the annotation if (this.props.linkDoc.followLinkLocation && this.props.linkDoc.followLinkLocation !== "Default") { this.props.addDocTab(this.props.destinationDoc, StrCast(this.props.linkDoc.followLinkLocation)); } else { DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.sourceDoc, doc => this.props.addDocTab(doc, "onRight"), false); } + + this.props.linkDoc.linksToAnnotation && setTimeout(() => window.open(StrCast(this.props.linkDoc.annotationUrl), '_blank'), 1000); // open external page if hypothes.is annotation } @undoBatch @action deleteLink = (): void => { + this.props.linkDoc.linksToAnnotation && Hypothesis.deleteLink(StrCast(this.props.linkDoc.annotationId), Utils.prepend("/doc/" + this.props.sourceDoc[Id])); // delete hyperlink in annotation + this.props.linkDoc.linksToAnnotation && console.log("annotationId", this.props.linkDoc.annotationId); LinkManager.Instance.deleteLink(this.props.linkDoc); LinkDocPreview.LinkInfo = undefined; DocumentLinksButton.EditLink = undefined; @@ -232,7 +239,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { <FontAwesomeIcon className="destination-icon" icon={destinationIcon} size="sm" /></div> <p className="linkMenu-destination-title" onPointerDown={this.followDefault}> - {title} + {this.props.linkDoc.linksToAnnotation ? "Annotation in" : ""} {title} </p> </div> {this.props.linkDoc.description !== "" ? <p className="linkMenu-description"> diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index b17accfd6..57fa26b80 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -1,18 +1,24 @@ import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast } from "../../../fields/Doc"; -import { emptyFunction, setupMoveUpEvents, returnFalse } from "../../../Utils"; +import { emptyFunction, setupMoveUpEvents, returnFalse, Utils } from "../../../Utils"; import { DragManager } from "../../util/DragManager"; import { UndoManager, undoBatch } from "../../util/UndoManager"; import './DocumentLinksButton.scss'; import { DocumentView } from "./DocumentView"; import React = require("react"); -import { DocUtils } from "../../documents/Documents"; +import { DocUtils, Docs } from "../../documents/Documents"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { LinkDocPreview } from "./LinkDocPreview"; import { LinkCreatedBox } from "./LinkCreatedBox"; +import { SelectionManager } from "../../util/SelectionManager"; +import { Document } from "../../../fields/documentSchemas"; +import { StrCast } from "../../../fields/Types"; + import { LinkDescriptionPopup } from "./LinkDescriptionPopup"; import { LinkManager } from "../../util/LinkManager"; +import { Hypothesis } from "../../apis/hypothesis/HypothesisApiUtils"; +import { Id } from "../../../fields/FieldSymbols"; import { Tooltip } from "@material-ui/core"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; @@ -30,6 +36,45 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp private _linkButton = React.createRef<HTMLDivElement>(); @observable public static StartLink: DocumentView | undefined; + @observable public static AnnotationId: string | undefined; + @observable public static AnnotationUri: string | undefined; + + componentDidMount() { + window.addEventListener("message", this.newAnnotation); // listen for a new Hypothes.is annotation from an iframe inside Dash + document.addEventListener("linkAnnotationToDash", this.linkAnnotation); // listen for event from Hypothes.is extension to link an existing annotation + } + + // start link from new Hypothes.is annotation + // TODO: pass in placeholderId directly from client + @action + newAnnotation = async (e: any) => { + if (e.origin === "http://localhost:1050" && e.data.message === "annotation created") { + console.log("DASH received message: annotation created"); + window.removeEventListener("message", this.newAnnotation); + const response = await Hypothesis.getPlaceholderId("placeholder"); + const source = SelectionManager.SelectedDocuments()[0]; + response && runInAction(() => { + DocumentLinksButton.AnnotationId = response.id; + DocumentLinksButton.AnnotationUri = response.uri; + DocumentLinksButton.StartLink = source; + }); + } + } + + @action + linkAnnotation = async (e: any) => { // event sent by hypothes.is plugin to tell Dash which annotation we're linking from + const annotationId = e.detail.id; + const annotationUri = e.detail.uri; + console.log(annotationId, annotationUri); + // const source = await Hypothesis.getWebDoc(annotationUri); + + const source = SelectionManager.SelectedDocuments()[0]; // TO BE FIXED, currently link just starts from whichever doc is selected + runInAction(() => { + DocumentLinksButton.AnnotationId = annotationId; + DocumentLinksButton.AnnotationUri = annotationUri; + DocumentLinksButton.StartLink = source; + }); + } @action @undoBatch onLinkButtonMoved = (e: PointerEvent) => { @@ -91,10 +136,22 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp if (doubleTap && this.props.InMenu && !!!this.props.StartLink) { if (DocumentLinksButton.StartLink === this.props.View) { DocumentLinksButton.StartLink = undefined; + DocumentLinksButton.AnnotationId = undefined; } else { - if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) { - const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag"); + const sourceDoc = DocumentLinksButton.StartLink.props.Document; + const targetDoc = this.props.View.props.Document; + const linkDoc = DocUtils.MakeLink({ doc: sourceDoc }, { doc: targetDoc }, DocumentLinksButton.AnnotationId ? "hypothes.is annotation" : "long drag"); + + // TODO: Not currently possible to drag to complete links to annotations + if (DocumentLinksButton.AnnotationId && DocumentLinksButton.AnnotationUri) { + const sourceUrl = DocumentLinksButton.AnnotationUri; + Doc.GetProto(linkDoc as Doc).linksToAnnotation = true; + Doc.GetProto(linkDoc as Doc).annotationId = DocumentLinksButton.AnnotationId; + Doc.GetProto(linkDoc as Doc).annotationUrl = Hypothesis.makeAnnotationUrl(DocumentLinksButton.AnnotationId, sourceUrl); // redirect web doc to this URL when following link + Hypothesis.makeLink(StrCast(targetDoc.title), Utils.prepend("/doc/" + targetDoc[Id]), DocumentLinksButton.AnnotationId); // update and link placeholder annotation + } + LinkManager.currentLink = linkDoc; runInAction(() => { @@ -121,15 +178,28 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp finishLinkClick = (e: React.MouseEvent) => { if (DocumentLinksButton.StartLink === this.props.View) { DocumentLinksButton.StartLink = undefined; + DocumentLinksButton.AnnotationId = undefined; + window.removeEventListener("message", this.newAnnotation); + window.addEventListener("message", this.newAnnotation); } else { if (this.props.InMenu && !!!this.props.StartLink) { if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) { - const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag"); + const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, DocumentLinksButton.AnnotationId ? "hypothes.is annotation" : "long drag"); // this notifies any of the subviews that a document is made so that they can make finer-grained hyperlinks (). see note above in onLInkButtonMoved runInAction(() => DocumentLinksButton.StartLink!._link = this.props.View._link = linkDoc); setTimeout(action(() => DocumentLinksButton.StartLink!._link = this.props.View._link = undefined), 0); LinkManager.currentLink = linkDoc; + // if the link is to a Hypothes.is annotation + if (DocumentLinksButton.AnnotationId && DocumentLinksButton.AnnotationUri) { + const sourceUrl = DocumentLinksButton.AnnotationUri; // the URL of the annotation's source web page + const targetDoc = this.props.View.props.Document; + Doc.GetProto(linkDoc as Doc).linksToAnnotation = true; + Doc.GetProto(linkDoc as Doc).annotationId = DocumentLinksButton.AnnotationId; + Doc.GetProto(linkDoc as Doc).annotationUrl = Hypothesis.makeAnnotationUrl(DocumentLinksButton.AnnotationId, sourceUrl); // redirect web doc to this URL when following link + Hypothesis.makeLink(StrCast(targetDoc.title), Utils.prepend("/doc/" + targetDoc[Id]), DocumentLinksButton.AnnotationId); // update and link placeholder annotation + } + runInAction(() => { if (linkDoc) { LinkCreatedBox.popupX = e.screenX; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 998c6798e..555e58bb0 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -42,6 +42,7 @@ import React = require("react"); import { DocumentLinksButton } from './DocumentLinksButton'; import { MobileInterface } from '../../../mobile/MobileInterface'; import { LinkCreatedBox } from './LinkCreatedBox'; +import { Hypothesis } from '../../apis/hypothesis/HypothesisApiUtils'; import { LinkDescriptionPopup } from './LinkDescriptionPopup'; import { LinkManager } from '../../util/LinkManager'; |
