diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/apis/hypothesis/HypothesisApiUtils.ts | 17 | ||||
-rw-r--r-- | src/client/documents/Documents.ts | 19 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/collections/CollectionLinearView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentLinksButton.tsx | 43 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 30 |
6 files changed, 108 insertions, 9 deletions
diff --git a/src/client/apis/hypothesis/HypothesisApiUtils.ts b/src/client/apis/hypothesis/HypothesisApiUtils.ts new file mode 100644 index 000000000..dc7e1f988 --- /dev/null +++ b/src/client/apis/hypothesis/HypothesisApiUtils.ts @@ -0,0 +1,17 @@ +export namespace Hypothesis { + export const getAnnotation = async (username: String, searchParam: String) => { + const base = 'https://api.hypothes.is/api/search'; + const request = base + `?user=acct:${username}@hypothes.is&text=${searchParam}`; + console.log("DASH Querying " + request); + const response = await fetch(request); + if (response.ok) { + return response.json(); + } else { + throw new Error('DASH: Error in GET request'); + } + }; + + export const makeAnnotationUrl = (annotationId: string, baseUrl: string) => { + return `https://hyp.is/${annotationId}/${baseUrl}`; + }; +}
\ No newline at end of file diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index fa85d58f0..8c3abada6 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -50,6 +50,7 @@ import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo"; import { DocumentType } from "./DocumentTypes"; import { Networking } from "../Network"; import { Upload } from "../../server/SharedMediaTypes"; +import { Hypothesis } from "../apis/hypothesis/HypothesisApiUtils"; const path = require('path'); export interface DocumentOptions { @@ -924,6 +925,24 @@ export namespace DocUtils { return linkDoc; } + export function MakeHypothesisLink(source: { doc: Doc }, target: { doc: Doc }, linkRelationship: string = "", sourceAnnotationId: string, id?: string) { + const sv = DocumentManager.Instance.getDocumentView(source.doc); + if (sv && sv.props.ContainingCollectionDoc === target.doc) return; + if (target.doc === Doc.UserDoc()) return undefined; + + const linkDoc = Docs.Create.LinkDocument(source, target, { linkRelationship, layoutKey: "layout_linkView" }, id); + linkDoc.layout_linkView = Cast(Cast(Doc.UserDoc()["template-button-link"], Doc, null).dragFactory, Doc, null); + Doc.GetProto(linkDoc).title = ComputedField.MakeFunction('self.anchor1?.title +" (" + (self.linkRelationship||"to") +") " + self.anchor2?.title'); + + console.log("sourceAnnotationId, should be url?", sourceAnnotationId, StrCast(source.doc.data)); + Doc.GetProto(linkDoc).sourceRedirectUrl = Hypothesis.makeAnnotationUrl(sourceAnnotationId, StrCast(source.doc.data)); + // Doc.GetProto(linkDoc).targetRedirectUrl = undefined; + + Doc.GetProto(source.doc).links = ComputedField.MakeFunction("links(self)"); + Doc.GetProto(target.doc).links = ComputedField.MakeFunction("links(self)"); + + return linkDoc; + } export function DocumentFromField(target: Doc, fieldKey: string, proto?: Doc, options?: DocumentOptions): Doc | undefined { let created: Doc | undefined; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 81195b550..cf1129895 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -111,6 +111,10 @@ export class MainView extends React.Component { } }); }); + // document.addEventListener("linkComplete", (e: any) => { // event used by Hypothes.is plugin to tell Dash when an annotation has been linked + // const annotatedUrl = e.details; + // console.log("This website " + annotatedUrl + " has a linked annotation"); + // }); } componentWillUnMount() { diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx index c370415be..f44c3db68 100644 --- a/src/client/views/collections/CollectionLinearView.tsx +++ b/src/client/views/collections/CollectionLinearView.tsx @@ -170,10 +170,14 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { }} onPointerDown={e => e.stopPropagation()} > <span className="bottomPopup-text" > +<<<<<<< HEAD + Creating link from: {(DocumentLinksButton.AnnotationId ? "Annotation in " : "")} {DocumentLinksButton.StartLink.title} </span> +======= Creating link from: {DocumentLinksButton.StartLink.title} </span> <span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting} > Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"} </span> +>>>>>>> 3f704ee2941fef77dd0eafebeb0a6ffb0a946a8b <span className="bottomPopup-exit" onClick={this.exitLongLinks} >Exit</span> diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 7fb447cab..61143a6af 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -7,10 +7,14 @@ import { UndoManager } 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"; const higflyout = require("@hig/flyout"); @@ -28,6 +32,23 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp private _linkButton = React.createRef<HTMLDivElement>(); @observable public static StartLink: DocumentView | undefined; + @observable public static AnnotationId: string | undefined; + + componentDidMount() { + // window.addEventListener("linkStarted", (e: any) => { // event used by Hypothes.is plugin to tell Dash when an unlinked annotation has been created + // const annotatedUrl = e.details; + // SelectionManager.SelectedDocuments().forEach(action((element: DocumentView) => { + // DocumentLinksButton.StartLink = element; + // })); + // }); + window.addEventListener("fakeLinkStarted", action((e: any) => { // event used by Hypothes.is plugin to tell Dash when an unlinked annotation has been created + console.log("Helo fake started link"); + const id = e.detail; + const source = SelectionManager.SelectedDocuments()[0]; + DocumentLinksButton.AnnotationId = id; + DocumentLinksButton.StartLink = source; + })); + } @action onLinkButtonMoved = (e: PointerEvent) => { @@ -86,13 +107,16 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp if (doubleTap) { if (DocumentLinksButton.StartLink === this.props.View) { DocumentLinksButton.StartLink = undefined; + DocumentLinksButton.AnnotationId = undefined; + console.log("reset to undefined (completeLink)"); // action((e: React.PointerEvent<HTMLDivElement>) => { // Doc.UnBrushDoc(this.props.View.Document); // }); } 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 linkDoc = DocumentLinksButton.AnnotationId ? + DocUtils.MakeHypothesisLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "hypothesis annotation", DocumentLinksButton.AnnotationId) : + DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag"); LinkManager.currentLink = linkDoc; runInAction(() => { LinkCreatedBox.popupX = e.screenX; @@ -115,23 +139,24 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp finishLinkClick = (e: React.MouseEvent) => { if (DocumentLinksButton.StartLink === this.props.View) { DocumentLinksButton.StartLink = undefined; + console.log("reset to undefined (finisheLinkClick)"); // action((e: React.PointerEvent<HTMLDivElement>) => { // Doc.UnBrushDoc(this.props.View.Document); // }); } 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 linkDoc = DocumentLinksButton.AnnotationId ? + DocUtils.MakeHypothesisLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "hypothesis annotation", DocumentLinksButton.AnnotationId) : + DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag"); LinkManager.currentLink = linkDoc; runInAction(() => { LinkCreatedBox.popupX = e.screenX; LinkCreatedBox.popupY = e.screenY - 133; LinkCreatedBox.linkCreated = true; - if (LinkDescriptionPopup.showDescriptions === "ON" || !LinkDescriptionPopup.showDescriptions) { - LinkDescriptionPopup.popupX = e.screenX; - LinkDescriptionPopup.popupY = e.screenY - 100; - LinkDescriptionPopup.descriptionPopup = true; - } + LinkDescriptionPopup.popupX = e.screenX; + LinkDescriptionPopup.popupY = e.screenY - 100; + LinkDescriptionPopup.descriptionPopup = true; setTimeout(action(() => { LinkCreatedBox.linkCreated = false; }), 2500); }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 97e3bc01c..9ad08a692 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -43,8 +43,12 @@ import React = require("react"); import { DocumentLinksButton } from './DocumentLinksButton'; import { MobileInterface } from '../../../mobile/MobileInterface'; import { LinkCreatedBox } from './LinkCreatedBox'; +<<<<<<< HEAD +import { Hypothesis } from '../../apis/hypothesis/HypothesisApiUtils'; +======= import { LinkDescriptionPopup } from './LinkDescriptionPopup'; import { LinkManager } from '../../util/LinkManager'; +>>>>>>> 3f704ee2941fef77dd0eafebeb0a6ffb0a946a8b library.add(fa.faEdit, fa.faTrash, fa.faShare, fa.faDownload, fa.faExpandArrowsAlt, fa.faCompressArrowsAlt, fa.faLayerGroup, fa.faExternalLinkAlt, fa.faAlignCenter, fa.faCaretSquareRight, fa.faSquare, fa.faConciergeBell, fa.faWindowRestore, fa.faFolder, fa.faMapPin, fa.faLink, fa.faFingerprint, fa.faCrosshairs, fa.faDesktop, fa.faUnlock, fa.faLock, fa.faLaptopCode, fa.faMale, @@ -773,6 +777,32 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu const cm = ContextMenu.Instance; if (!cm) return; + cm.addItem({ + description: "make hypothesis link", event: async () => { + const docUrl = Utils.prepend("/doc/" + this.props.Document[Id]); + const docTitle = StrCast(this.layoutDoc.title); + const getResponse = await Hypothesis.getAnnotation("melissaz", "placeholder"); + if (getResponse && getResponse.rows.length > 0) { + const annotationId = getResponse.rows[0].id; + document.dispatchEvent(new CustomEvent<{ url: string, title: string, id: string }>("linkRequest", { + detail: { url: docUrl, title: docTitle, id: annotationId }, + bubbles: true + })); + } else { + console.log("no placeholder annotation found"); + } + }, icon: "eye" + }); + + cm.addItem({ + description: "pretend we made an annotation", event: () => { + document.dispatchEvent(new CustomEvent("fakeLinkStarted", { + detail: "fakefakefakeid", + bubbles: true + })); + }, icon: "eye" + }); + const customScripts = Cast(this.props.Document.contextMenuScripts, listSpec(ScriptField), []); Cast(this.props.Document.contextMenuLabels, listSpec("string"), []).forEach((label, i) => cm.addItem({ description: label, event: () => customScripts[i]?.script.run({ this: this.layoutDoc, self: this.rootDoc }), icon: "sticky-note" })); |