From 2579a16d5fb79a80a603e1e3574ed2548b1a77db Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 17 Jun 2021 19:42:28 -0400 Subject: from last --- src/client/views/pdf/PDFViewer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/views/pdf') diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 85cf5abd7..3c6cad42f 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -372,7 +372,7 @@ export class PDFViewer extends React.Component { if ((e.button !== 0 || e.altKey) && this.props.isContentActive(true)) { this._setPreviewCursor?.(e.clientX, e.clientY, true); } - if (!e.altKey && e.button === 0 && this.props.isContentActive(true)) { + if (!e.altKey && e.button === 0 && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen].includes(CurrentUserUtils.SelectedTool)) { this.props.select(false); this._marqueeing = [e.clientX, e.clientY]; if (e.target && ((e.target as any).className.includes("endOfContent") || ((e.target as any).parentElement.className !== "textLayer"))) { -- cgit v1.2.3-70-g09d2 From 464bca333ba97185dcbc93409001adeb26711902 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 1 Jul 2021 22:43:47 -0400 Subject: added ability to create anchors in PDF/Webboxes by making a selection and clicking the start link button --- src/client/views/MarqueeAnnotator.tsx | 8 ++++---- src/client/views/nodes/PDFBox.tsx | 13 ++++++++----- src/client/views/nodes/WebBox.tsx | 19 +++++++++++-------- src/client/views/pdf/AnchorMenu.tsx | 1 + src/client/views/pdf/PDFViewer.tsx | 8 ++++---- 5 files changed, 28 insertions(+), 21 deletions(-) (limited to 'src/client/views/pdf') diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index d2074d653..b5df7b79b 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -65,10 +65,9 @@ export class MarqueeAnnotator extends React.Component { doc.addEventListener("pointermove", this.onSelectMove); doc.addEventListener("pointerup", this.onSelectEnd); - AnchorMenu.Instance.OnClick = (e: PointerEvent) => { - this.props.anchorMenuClick?.()?.(this.highlight("rgba(173, 216, 230, 0.75)", true)); - }; + AnchorMenu.Instance.OnClick = (e: PointerEvent) => this.props.anchorMenuClick?.()?.(this.highlight("rgba(173, 216, 230, 0.75)", true)); AnchorMenu.Instance.Highlight = this.highlight; + AnchorMenu.Instance.GetAnchor = () => this.highlight("rgba(173, 216, 230, 0.75)", true); /** * This function is used by the AnchorMenu to create an anchor highlight and a new linked text annotation. * It also initiates a Drag/Drop interaction to place the text annotation. @@ -105,7 +104,8 @@ export class MarqueeAnnotator extends React.Component { @action makeAnnotationDocument = (color: string, isLinkButton?: boolean): Opt => { if (this.props.savedAnnotations.size === 0) return undefined; - if ((Array.from(this.props.savedAnnotations.values())[0][0] as any).marqueeing) { + const savedAnnos = Array.from(this.props.savedAnnotations.values())[0]; + if (savedAnnos.length && (savedAnnos[0] as any).marqueeing) { const scale = this.props.scaling?.() || 1; const anno = Array.from(this.props.savedAnnotations.values())[0][0]; const containerOffset = this.props.containerOffset?.() || [0, 0]; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index feaeb9e21..8f61e252b 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -23,6 +23,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import { pageSchema } from "./ImageBox"; import "./PDFBox.scss"; import React = require("react"); +import { AnchorMenu } from '../pdf/AnchorMenu'; type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>; const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema); @@ -94,11 +95,13 @@ export class PDFBox extends ViewBoxAnnotatableComponent { - const anchor = Docs.Create.TextanchorDocument({ - title: StrCast(this.rootDoc.title + " " + this.layoutDoc._scrollTop), - annotationOn: this.rootDoc, - y: NumCast(this.layoutDoc._scrollTop), - }); + const anchor = + AnchorMenu.Instance?.GetAnchor() ?? + Docs.Create.TextanchorDocument({ + title: StrCast(this.rootDoc.title + " " + this.layoutDoc._scrollTop), + annotationOn: this.rootDoc, + y: NumCast(this.layoutDoc._scrollTop), + }); this.addDocument(anchor); return anchor; } diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index bd9e03856..a16881b66 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -88,9 +88,10 @@ export class WebBox extends ViewBoxAnnotatableComponent this.props.isSelected(), selected => !selected && setTimeout(() => { - Array.from(this._savedAnnotations.values()).forEach(v => v.forEach(a => a.remove())); - this._savedAnnotations.clear(); - })); + // Array.from(this._savedAnnotations.values()).forEach(v => v.forEach(a => a.remove())); + // this._savedAnnotations.clear(); + }) + ); if (this.webField?.href.indexOf("youtube") !== -1) { const youtubeaspect = 400 / 315; @@ -174,11 +175,13 @@ export class WebBox extends ViewBoxAnnotatableComponent { - const anchor = Docs.Create.TextanchorDocument({ - title: StrCast(this.rootDoc.title + " " + this.layoutDoc._scrollTop), - annotationOn: this.rootDoc, - y: NumCast(this.layoutDoc._scrollTop), - }); + const anchor = + AnchorMenu.Instance?.GetAnchor() ?? + Docs.Create.TextanchorDocument({ + title: StrCast(this.rootDoc.title + " " + this.layoutDoc._scrollTop), + annotationOn: this.rootDoc, + y: NumCast(this.layoutDoc._scrollTop), + }); this.addDocument(anchor); return anchor; } diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index 1e2d72254..86b124de5 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -46,6 +46,7 @@ export class AnchorMenu extends AntimodeMenu { public OnClick: (e: PointerEvent) => void = unimplementedFunction; public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; public Highlight: (color: string, isPushpin: boolean) => Opt = (color: string, isPushpin: boolean) => undefined; + public GetAnchor: () => Opt = () => undefined; public Delete: () => void = unimplementedFunction; public AddTag: (key: string, value: string) => boolean = returnFalse; public PinToPres: () => void = unimplementedFunction; diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 3c6cad42f..4a50dccf3 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -133,10 +133,10 @@ export class PDFViewer extends React.Component { this._disposers.selected = reaction(() => this.props.isSelected(), selected => { - if (!selected) { - Array.from(this._savedAnnotations.values()).forEach(v => v.forEach(a => a.remove())); - Array.from(this._savedAnnotations.keys()).forEach(k => this._savedAnnotations.set(k, [])); - } + // if (!selected) { + // Array.from(this._savedAnnotations.values()).forEach(v => v.forEach(a => a.remove())); + // Array.from(this._savedAnnotations.keys()).forEach(k => this._savedAnnotations.set(k, [])); + // } (SelectionManager.Views().length === 1) && this.setupPdfJsViewer(); }, { fireImmediately: true }); -- cgit v1.2.3-70-g09d2 From 3c834ee55899b91f5fff8cfe5c808607f942b9f3 Mon Sep 17 00:00:00 2001 From: dinhanhtruong <70963346+dinhanhtruong@users.noreply.github.com> Date: Thu, 8 Jul 2021 15:51:26 -0400 Subject: created front-end link popup on text highlight added button to AnchorMenu marquee selector for showing the link popup after highlighting text. created the front end of the popup. need to fix visibility when clicking out --- src/client/views/AntimodeMenu.scss | 1 - src/client/views/linking/LinkPopup.scss | 40 +++++++++ src/client/views/linking/LinkPopup.tsx | 94 ++++++++++++++++++++++ src/client/views/nodes/DocumentLinksButton.tsx | 18 +++-- src/client/views/nodes/LinkDocPreview.tsx | 4 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 2 +- src/client/views/pdf/AnchorMenu.tsx | 17 ++++ 7 files changed, 166 insertions(+), 10 deletions(-) create mode 100644 src/client/views/linking/LinkPopup.scss create mode 100644 src/client/views/linking/LinkPopup.tsx (limited to 'src/client/views/pdf') diff --git a/src/client/views/AntimodeMenu.scss b/src/client/views/AntimodeMenu.scss index a275901be..468ee838d 100644 --- a/src/client/views/AntimodeMenu.scss +++ b/src/client/views/AntimodeMenu.scss @@ -8,7 +8,6 @@ background: #323232; box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); // border-radius: 0px 6px 6px 6px; - z-index: 1001; display: flex; &.with-rows { diff --git a/src/client/views/linking/LinkPopup.scss b/src/client/views/linking/LinkPopup.scss new file mode 100644 index 000000000..009a21bd6 --- /dev/null +++ b/src/client/views/linking/LinkPopup.scss @@ -0,0 +1,40 @@ +.linkPopup-container { + background: white; + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23); + top: 35px; + height: 200px; + width: 200px; + position: absolute; + padding: 10px; + border-radius: 3px; + + input { + border: 1px solid #b9b9b9; + border-radius: 20px; + height: 25px; + width: 100%; + padding-left: 10px; + } + + .divider { + margin: 10px 0; + height: 20px; + width: 100%; + + .line { + height: 1px; + background-color: #b9b9b9; + width: 100%; + position: relative; + top: 12px; + } + + .divider-text { + width: 20px; + background-color: white; + text-align: center; + position: relative; + margin: auto; + } + } +} \ No newline at end of file diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx new file mode 100644 index 000000000..71db06f19 --- /dev/null +++ b/src/client/views/linking/LinkPopup.tsx @@ -0,0 +1,94 @@ +import { IconProp } from '@fortawesome/fontawesome-svg-core'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Tooltip } from '@material-ui/core'; +import { action, observable, runInAction } from 'mobx'; +import { observer } from "mobx-react"; +import { Doc, DocListCast } from '../../../fields/Doc'; +import { Cast, StrCast } from '../../../fields/Types'; +import { WebField } from '../../../fields/URLField'; +import { emptyFunction, setupMoveUpEvents, returnFalse, returnTrue, returnEmptyDoclist, returnEmptyFilter } from '../../../Utils'; +import { DocumentType } from '../../documents/DocumentTypes'; +import { DocumentManager } from '../../util/DocumentManager'; +import { DragManager } from '../../util/DragManager'; +import { Hypothesis } from '../../util/HypothesisUtils'; +import { LinkManager } from '../../util/LinkManager'; +import { undoBatch } from '../../util/UndoManager'; +import { DocumentLinksButton } from '../nodes/DocumentLinksButton'; +import { DocumentView, DocumentViewSharedProps } from '../nodes/DocumentView'; +import { LinkDocPreview } from '../nodes/LinkDocPreview'; +import './LinkPopup.scss'; +import React = require("react"); +import { CurrentUserUtils } from '../../util/CurrentUserUtils'; +import { DefaultStyleProvider } from '../StyleProvider'; +import { Transform } from 'stream'; +import { DocUtils } from '../../documents/Documents'; +import { SearchBox } from '../search/SearchBox'; + +interface LinkPopupProps { + showPopup: boolean; + // groupType: string; + // linkDoc: Doc; + // docView: DocumentView; + // sourceDoc: Doc; +} + +/** + * Popup component for creating links from text to Dash documents + */ + +@observer +export class LinkPopup extends React.Component { + + render() { + const popupVisibility = this.props.showPopup ? "block" : "none"; + return ( +
+ +
+ + +
+
+
+

or

+
+
+ + + + {/* + */} +
+
+ ); + } +} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index a6d07374a..046a8c856 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -30,12 +30,12 @@ interface DocumentLinksButtonProps { Offset?: (number | undefined)[]; AlwaysOn?: boolean; InMenu?: boolean; - StartLink?: boolean; + StartLink?: boolean; //whether the link HAS been started (i.e. now needs to be completed) } @observer export class DocumentLinksButton extends React.Component { private _linkButton = React.createRef(); - @observable public static StartLink: Doc | undefined; + @observable public static StartLink: Doc | undefined; //origin's Doc, if defined @observable public static StartLinkView: DocumentView | undefined; @observable public static AnnotationId: string | undefined; @observable public static AnnotationUri: string | undefined; @@ -45,6 +45,7 @@ export class DocumentLinksButton extends React.Component(); @action public static ClearLinkEditor() { DocumentLinksButton.LinkEditorDocView = undefined; } + @action @undoBatch onLinkButtonMoved = (e: PointerEvent) => { if (this.props.InMenu && this.props.StartLink) { @@ -120,7 +121,7 @@ export class DocumentLinksButton extends React.Component { setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action((e, doubleTap) => { if (doubleTap && !this.props.StartLink) { @@ -141,7 +143,7 @@ export class DocumentLinksButton extends React.Component; @@ -263,7 +268,7 @@ export class DocumentLinksButton extends React.Component - {this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? + {this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? //if the origin node is not this node
DocumentLinksButton.StartLink && DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View)} /> : (null) } - {DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.InMenu && this.props.StartLink ? + {DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.InMenu && this.props.StartLink ? //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again
: (null) } @@ -290,6 +295,7 @@ export class DocumentLinksButton extends React.Component{title}
}> diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 65afbe131..b73fb10df 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -110,11 +110,11 @@ export class LinkDocPreview extends React.Component { } } width = () => { - if (!this._targetDoc) return 500; + if (!this._targetDoc) return 225; if (this._targetDoc[WidthSym]() < this._targetDoc?.[HeightSym]()) { return Math.min(225, this._targetDoc[HeightSym]()) * this._targetDoc[WidthSym]() / this._targetDoc[HeightSym](); } - return Math.min(500, NumCast(this._targetDoc?.[WidthSym](), 500)); + return Math.min(225, NumCast(this._targetDoc?.[WidthSym](), 225)); } height = () => { if (!this._targetDoc) return 225; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 911ec1560..5180732b9 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1398,7 +1398,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp SelectionManager.DeselectAll(); RichTextMenu.Instance.updateMenu(undefined, undefined, undefined); return; - case "Enter": this.insertTime(); + case "Enter": this.insertTime(); case "Tab": e.preventDefault(); break; default: if (this._lastTimedMark?.attrs.userid === Doc.CurrentUserEmail) break; case " ": diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index 1e2d72254..4d9dbe7a0 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -10,6 +10,7 @@ import { AntimodeMenu, AntimodeMenuProps } from "../AntimodeMenu"; import { ButtonDropdown } from "../nodes/formattedText/RichTextMenu"; import "./AnchorMenu.scss"; import { SelectionManager } from "../../util/SelectionManager"; +import { LinkPopup } from "../linking/LinkPopup"; @observer export class AnchorMenu extends AntimodeMenu { @@ -38,6 +39,7 @@ export class AnchorMenu extends AntimodeMenu { @observable private _valueValue: string = ""; @observable private _added: boolean = false; @observable private highlightColor: string = "rgba(245, 230, 95, 0.616)"; + @observable private _showLinkPopup: boolean = false; @observable public _colorBtn = false; @observable public Highlighting: boolean = false; @@ -79,6 +81,14 @@ export class AnchorMenu extends AntimodeMenu { } } + @action + toggleLinkPopup = (e: React.MouseEvent) => { + //ignore the potential null type error because this method cannot be called unless the user selects text and clicks the link button + console.log(window.getSelection().toString()) + //change popup visibility field to visible + this._showLinkPopup = !this._showLinkPopup; + } + @computed get highlighter() { const button = , + + {"Link selected text to document or URL"}
}> + + , + ] : [ {"Remove Link Anchor"}}> , - {"Link selected text to document or URL"}}> - - , - + //NOTE: link popup is currently incomplete + // {"Link selected text to document or URL"}}> + // + // , + // ] : [ {"Remove Link Anchor"}}>