aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/apis/hypothesis/HypothesisApiUtils.ts17
-rw-r--r--src/client/documents/Documents.ts19
-rw-r--r--src/client/views/MainView.tsx4
-rw-r--r--src/client/views/collections/CollectionLinearView.tsx2
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx34
-rw-r--r--src/client/views/nodes/DocumentView.tsx27
6 files changed, 99 insertions, 4 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 3355c0091..27f61a128 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 {
@@ -923,6 +924,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 eba9bb344..9221b27a5 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -109,6 +109,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 7cbe5c19d..fd8eb506a 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -154,7 +154,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
}}
onPointerDown={e => e.stopPropagation()} >
<span className="bottomPopup-text" >
- Creating link from: {DocumentLinksButton.StartLink.title} </span>
+ Creating link from: {(DocumentLinksButton.AnnotationId ? "Annotation in " : "")} {DocumentLinksButton.StartLink.title} </span>
<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 bfd860f65..f12472b01 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";
+
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -26,6 +30,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) => {
@@ -83,12 +104,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 {
DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View &&
- DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
+ (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"));
runInAction(() => {
LinkCreatedBox.popupX = e.screenX;
@@ -105,12 +130,15 @@ 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 {
DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View &&
- DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag");
+ (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"));
runInAction(() => {
LinkCreatedBox.popupX = e.screenX;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 3311bfa33..0e5b09f8b 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -43,6 +43,7 @@ import React = require("react");
import { DocumentLinksButton } from './DocumentLinksButton';
import { MobileInterface } from '../../../mobile/MobileInterface';
import { LinkCreatedBox } from './LinkCreatedBox';
+import { Hypothesis } from '../../apis/hypothesis/HypothesisApiUtils';
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,
@@ -755,6 +756,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" }));