diff options
Diffstat (limited to 'src/client')
| -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 | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentLinksButton.tsx | 34 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 27 | 
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" })); | 
