aboutsummaryrefslogtreecommitdiff
path: root/src/client/views
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views')
-rw-r--r--src/client/views/GlobalKeyHandler.ts2
-rw-r--r--src/client/views/MainView.tsx5
-rw-r--r--src/client/views/collections/CollectionLinearView.tsx2
-rw-r--r--src/client/views/collections/CollectionSubView.tsx5
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx2
-rw-r--r--src/client/views/linking/LinkEditor.tsx6
-rw-r--r--src/client/views/linking/LinkMenuItem.tsx21
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx127
8 files changed, 114 insertions, 56 deletions
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index c9f95a538..b4a518326 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -7,7 +7,6 @@ import { List } from "../../fields/List";
import { ScriptField } from "../../fields/ScriptField";
import { Cast, PromiseValue } from "../../fields/Types";
import GoogleAuthenticationManager from "../apis/GoogleAuthenticationManager";
-import HypothesisAuthenticationManager from "../apis/HypothesisAuthenticationManager";
import { DocServer } from "../DocServer";
import { DocumentType } from "../documents/DocumentTypes";
import { DictationManager } from "../util/DictationManager";
@@ -106,7 +105,6 @@ export default class KeyManager {
doDeselect && SelectionManager.DeselectAll();
DictationManager.Controls.stop();
GoogleAuthenticationManager.Instance.cancel();
- HypothesisAuthenticationManager.Instance.cancel();
SharingManager.Instance.close();
GroupManager.Instance.close();
CollectionFreeFormViewChrome.Instance.clearKeep();
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 66545ea1f..fccfe325a 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -16,7 +16,6 @@ import { BoolCast, Cast, FieldValue, StrCast } from '../../fields/Types';
import { TraceMobx } from '../../fields/util';
import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../Utils';
import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager';
-import HypothesisAuthenticationManager from '../apis/HypothesisAuthenticationManager';
import { DocServer } from '../DocServer';
import { Docs, DocumentOptions } from '../documents/Documents';
import { DocumentType } from '../documents/DocumentTypes';
@@ -59,6 +58,7 @@ import { TaskCompletionBox } from './nodes/TaskCompletedBox';
import { OverlayView } from './OverlayView';
import PDFMenu from './pdf/PDFMenu';
import { PreviewCursor } from './PreviewCursor';
+import { Hypothesis } from '../apis/hypothesis/HypothesisUtils';
import { undoBatch } from '../util/UndoManager';
@observer
@@ -125,6 +125,7 @@ export class MainView extends React.Component {
}
});
});
+ document.addEventListener("linkAnnotationToDash", Hypothesis.linkListener);
}
componentWillUnMount() {
@@ -132,6 +133,7 @@ export class MainView extends React.Component {
window.removeEventListener("pointerdown", this.globalPointerDown);
window.removeEventListener("pointerup", this.globalPointerUp);
window.removeEventListener("paste", KeyManager.Instance.paste as any);
+ document.removeEventListener("linkAnnotationToDash", Hypothesis.linkListener);
}
constructor(props: Readonly<{}>) {
@@ -727,7 +729,6 @@ export class MainView extends React.Component {
<SettingsManager />
<GroupManager />
<GoogleAuthenticationManager />
- <HypothesisAuthenticationManager />
<DocumentDecorations />
{/* {this.search} */}
<CollectionMenu />
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index a9e812ad3..19d1ffa7b 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.props.Document.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/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 3ebc6baca..5906282f1 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -351,8 +351,9 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
title: uriList,
_width: 400,
_height: 315,
- _nativeWidth: 600,
- _nativeHeight: 472.5
+ _nativeWidth: 850,
+ _nativeHeight: 962,
+ UseCors: true
}));
return;
}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index a32c8b363..4334a339a 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -74,7 +74,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
if (e.key === "?") {
ContextMenu.Instance.setDefaultItem("?", (str: string) => {
const textDoc = Docs.Create.WebDocument(`https://bing.com/search?q=${str}`, {
- _width: 200, x, y, _nativeHeight: 962, _nativeWidth: 800, isAnnotating: false,
+ _width: 200, x, y, _nativeHeight: 962, _nativeWidth: 850, isAnnotating: false,
title: "bing", UseCors: true
});
this.props.addDocTab(textDoc, "onRight");
diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx
index 660afd4b9..fb014af51 100644
--- a/src/client/views/linking/LinkEditor.tsx
+++ b/src/client/views/linking/LinkEditor.tsx
@@ -388,6 +388,12 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
onPointerDown={() => this.changeFollowBehavior("inTab")}>
Always open in new tab
</div>
+ {this.props.linkDoc.linksToAnnotation ?
+ <div className="linkEditor-followingDropdown-option"
+ onPointerDown={() => this.changeFollowBehavior("openExternal")}>
+ Always open in external page
+ </div>
+ : null}
</div>
</div>
</div>;
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 6feb0a398..b29754d45 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -11,13 +11,16 @@ 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, simulateMouseClick } from '../../../Utils';
import { DocumentView } from '../nodes/DocumentView';
import { DocumentLinksButton } from '../nodes/DocumentLinksButton';
import { LinkDocPreview } from '../nodes/LinkDocPreview';
+import { Hypothesis } from '../../apis/hypothesis/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);
@@ -151,17 +154,27 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
async followDefault() {
DocumentLinksButton.EditLink = undefined;
LinkDocPreview.LinkInfo = undefined;
+ const linkDoc = this.props.linkDoc;
- if (this.props.linkDoc.followLinkLocation && this.props.linkDoc.followLinkLocation !== "Default") {
- this.props.addDocTab(this.props.destinationDoc, StrCast(this.props.linkDoc.followLinkLocation));
+ if (linkDoc.followLinkLocation === "openExternal" && this.props.destinationDoc.type === DocumentType.WEB) {
+ window.open(`${StrCast(linkDoc.annotationUri)}#annotations:${StrCast(linkDoc.annotationId)}`, '_blank');
+ return;
+ }
+
+ if (linkDoc.followLinkLocation && linkDoc.followLinkLocation !== "Default") {
+ this.props.addDocTab(this.props.destinationDoc, StrCast(linkDoc.followLinkLocation));
} else {
DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.sourceDoc, doc => this.props.addDocTab(doc, "onRight"), false);
}
+
+ linkDoc.linksToAnnotation && Hypothesis.scrollToAnnotation(StrCast(this.props.linkDoc.annotationId));
}
@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;
@@ -234,7 +247,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 && Cast(this.props.destinationDoc.data, WebField)?.url.href === this.props.linkDoc.annotationUri ? "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 31efaaaa6..00477874b 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -2,18 +2,24 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Tooltip } from "@material-ui/core";
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
-import { Doc } from "../../../fields/Doc";
+import { Doc, DocListCast } from "../../../fields/Doc";
+import { DocumentType } from "../../documents/DocumentTypes";
+import { emptyFunction, setupMoveUpEvents, returnFalse, Utils, emptyPath } from "../../../Utils";
import { TraceMobx } from "../../../fields/util";
-import { emptyFunction, returnFalse, setupMoveUpEvents, emptyPath } from "../../../Utils";
import { DocUtils } from "../../documents/Documents";
import { DragManager } from "../../util/DragManager";
import { LinkManager } from "../../util/LinkManager";
import { undoBatch, UndoManager } from "../../util/UndoManager";
-import './DocumentLinksButton.scss';
import { DocumentView } from "./DocumentView";
+import { StrCast, Cast } from "../../../fields/Types";
import { LinkDescriptionPopup } from "./LinkDescriptionPopup";
+import { Hypothesis } from "../../apis/hypothesis/HypothesisUtils";
+import { Id } from "../../../fields/FieldSymbols";
import { TaskCompletionBox } from "./TaskCompletedBox";
import React = require("react");
+import './DocumentLinksButton.scss';
+import { WebField } from "../../../fields/URLField";
+
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -30,7 +36,9 @@ interface DocumentLinksButtonProps {
export class DocumentLinksButton extends React.Component<DocumentLinksButtonProps, {}> {
private _linkButton = React.createRef<HTMLDivElement>();
- @observable public static StartLink: DocumentView | undefined;
+ @observable public static StartLink: Doc | undefined;
+ @observable public static AnnotationId: string | undefined;
+ @observable public static AnnotationUri: string | undefined;
@action @undoBatch
onLinkButtonMoved = (e: PointerEvent) => {
@@ -67,10 +75,10 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
setupMoveUpEvents(this, e, this.onLinkButtonMoved, emptyFunction, action((e, doubleTap) => {
if (doubleTap && this.props.InMenu && this.props.StartLink) {
//action(() => Doc.BrushDoc(this.props.View.Document));
- if (DocumentLinksButton.StartLink === this.props.View) {
+ if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
DocumentLinksButton.StartLink = undefined;
} else {
- DocumentLinksButton.StartLink = this.props.View;
+ DocumentLinksButton.StartLink = this.props.View.props.Document;
}
} else if (!this.props.InMenu) {
DocumentLinksButton.EditLink = this.props.View;
@@ -82,10 +90,10 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
@action @undoBatch
onLinkClick = (e: React.MouseEvent): void => {
if (this.props.InMenu && this.props.StartLink) {
- if (DocumentLinksButton.StartLink === this.props.View) {
+ if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
DocumentLinksButton.StartLink = undefined;
} else {
- DocumentLinksButton.StartLink = this.props.View;
+ DocumentLinksButton.StartLink = this.props.View.props.Document;
}
//action(() => Doc.BrushDoc(this.props.View.Document));
@@ -97,50 +105,80 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
completeLink = (e: React.PointerEvent): void => {
setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action((e, doubleTap) => {
- if (doubleTap && this.props.InMenu && !this.props.StartLink) {
- if (DocumentLinksButton.StartLink === this.props.View) {
+ if (doubleTap && !this.props.StartLink) {
+ if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
DocumentLinksButton.StartLink = 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");
- LinkManager.currentLink = linkDoc;
- if (linkDoc) {
- TaskCompletionBox.textDisplayed = "Link Created";
- TaskCompletionBox.popupX = e.screenX;
- TaskCompletionBox.popupY = e.screenY - 133;
- TaskCompletionBox.taskCompleted = true;
-
- LinkDescriptionPopup.popupX = e.screenX;
- LinkDescriptionPopup.popupY = e.screenY - 100;
- LinkDescriptionPopup.descriptionPopup = true;
+ DocumentLinksButton.AnnotationId = undefined;
+ } else if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document) {
+ const sourceDoc = DocumentLinksButton.StartLink;
+ const targetDoc = this.props.View.props.Document;
+ const linkDoc = DocUtils.MakeLink({ doc: sourceDoc }, { doc: targetDoc }, DocumentLinksButton.AnnotationId ? "hypothes.is annotation" : "long drag");
- setTimeout(action(() => TaskCompletionBox.taskCompleted = false), 2500);
+ // TODO: Not currently possible to drag to complete links to annotations
+ if (DocumentLinksButton.AnnotationId && DocumentLinksButton.AnnotationUri) {
+ Doc.GetProto(linkDoc as Doc).linksToAnnotation = true;
+ Doc.GetProto(linkDoc as Doc).annotationId = DocumentLinksButton.AnnotationId;
+ Doc.GetProto(linkDoc as Doc).annotationUri = DocumentLinksButton.AnnotationUri;
+ Hypothesis.makeLink(StrCast(targetDoc.title), Utils.prepend("/doc/" + targetDoc[Id]), DocumentLinksButton.AnnotationId); // update and link placeholder annotation
}
+
+ LinkManager.currentLink = linkDoc;
+
+ runInAction(() => {
+ if (linkDoc) {
+ TaskCompletionBox.textDisplayed = "Link Created";
+ TaskCompletionBox.popupX = e.screenX;
+ TaskCompletionBox.popupY = e.screenY - 133;
+ TaskCompletionBox.taskCompleted = true;
+
+ 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(() => TaskCompletionBox.taskCompleted = false), 2500);
+ }
+ });
}
}
})));
}
finishLinkClick = undoBatch(action((screenX: number, screenY: number) => {
- if (DocumentLinksButton.StartLink === this.props.View) {
+ if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
DocumentLinksButton.StartLink = undefined;
- } else if (this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) {
- const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "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
- DocumentLinksButton.StartLink!._link = this.props.View._link = linkDoc;
- setTimeout(action(() => DocumentLinksButton.StartLink!._link = this.props.View._link = undefined), 0);
- LinkManager.currentLink = linkDoc;
- if (linkDoc) {
- TaskCompletionBox.textDisplayed = "Link Created";
- TaskCompletionBox.popupX = screenX;
- TaskCompletionBox.popupY = screenY - 133;
- TaskCompletionBox.taskCompleted = true;
-
- if (LinkDescriptionPopup.showDescriptions === "ON" || !LinkDescriptionPopup.showDescriptions) {
- LinkDescriptionPopup.popupX = screenX;
- LinkDescriptionPopup.popupY = screenY - 100;
- LinkDescriptionPopup.descriptionPopup = true;
+ DocumentLinksButton.AnnotationId = undefined;
+ } else {
+ if (!this.props.StartLink && DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document) {
+ const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink }, { 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
+ DocumentLinksButton.StartLink._link = this.props.View._link = linkDoc;
+ setTimeout(action(() => DocumentLinksButton.StartLink!._link = this.props.View._link = undefined), 0);
+ LinkManager.currentLink = linkDoc;
+
+ if (DocumentLinksButton.AnnotationId && DocumentLinksButton.AnnotationUri) { // if linking from a Hypothes.is annotation
+ 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).annotationUri = DocumentLinksButton.AnnotationUri;
+ Hypothesis.makeLink(StrCast(targetDoc.title), Utils.prepend("/doc/" + targetDoc[Id]), DocumentLinksButton.AnnotationId); // edit annotation to add a Dash hyperlink to the linked doc
}
- setTimeout(action(() => TaskCompletionBox.taskCompleted = false), 2500);
+ if (linkDoc) {
+ TaskCompletionBox.textDisplayed = "Link Created";
+ TaskCompletionBox.popupX = screenX;
+ TaskCompletionBox.popupY = screenY - 133;
+ TaskCompletionBox.taskCompleted = true;
+
+ if (LinkDescriptionPopup.showDescriptions === "ON" || !LinkDescriptionPopup.showDescriptions) {
+ LinkDescriptionPopup.popupX = screenX;
+ LinkDescriptionPopup.popupY = screenY - 100;
+ LinkDescriptionPopup.descriptionPopup = true;
+ }
+ setTimeout(action(() => { TaskCompletionBox.taskCompleted = false; }), 2500);
+ }
}
}
}));
@@ -203,7 +241,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
</div>
{this.props.InMenu && !this.props.StartLink &&
- DocumentLinksButton.StartLink !== this.props.View ? <div className={"documentLinksButton-endLink"}
+ DocumentLinksButton.StartLink !== this.props.View.props.Document ? <div className={"documentLinksButton-endLink"}
style={{
width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px",
backgroundColor: DocumentLinksButton.StartLink ? "" : "grey",
@@ -211,11 +249,11 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
}}
onPointerDown={DocumentLinksButton.StartLink ? this.completeLink : emptyFunction}
onClick={e => DocumentLinksButton.StartLink ? this.finishLinkClick(e.screenX, e.screenY) : emptyFunction} /> : (null)}
- {DocumentLinksButton.StartLink === this.props.View && this.props.InMenu && this.props.StartLink ? <div className={"documentLinksButton-startLink"}
+ {DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.InMenu && this.props.StartLink ? <div className={"documentLinksButton-startLink"}
style={{ width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px" }}
onPointerDown={this.clearLinks} onClick={this.clearLinks}
/> : (null)}
- </div>;
+ </div >;
return (!links.length) && !this.props.AlwaysOn ? (null) :
this.props.InMenu && (this.props.StartLink || DocumentLinksButton.StartLink) ?
@@ -227,6 +265,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
</Tooltip> :
linkButton;
}
+
render() {
return this.linkButton;
}