aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordinhanhtruong <70963346+dinhanhtruong@users.noreply.github.com>2021-07-08 15:51:26 -0400
committerdinhanhtruong <70963346+dinhanhtruong@users.noreply.github.com>2021-07-08 15:51:26 -0400
commit3c834ee55899b91f5fff8cfe5c808607f942b9f3 (patch)
treea3bc53d8e732996254a5db0746bdd850ce2bc1a5 /src
parent61f5e6edac1967480e31c6407e3505eea2a08c26 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/client/views/AntimodeMenu.scss1
-rw-r--r--src/client/views/linking/LinkPopup.scss40
-rw-r--r--src/client/views/linking/LinkPopup.tsx94
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx18
-rw-r--r--src/client/views/nodes/LinkDocPreview.tsx4
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx2
-rw-r--r--src/client/views/pdf/AnchorMenu.tsx17
7 files changed, 166 insertions, 10 deletions
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<LinkPopupProps> {
+
+ render() {
+ const popupVisibility = this.props.showPopup ? "block" : "none";
+ return (
+ <div className="linkPopup-container" style={{ display: popupVisibility }}>
+
+ <div className="linkPopup-url-container">
+ <input defaultValue={""} autoComplete="off" type="text" placeholder="Enter URL..." id="url-input"
+ className="linkPopup-searchBox searchBox-input" />
+ <button style={{ display: "block", margin: "10px auto", }}>Apply hyperlink</button>
+ </div>
+ <div className="divider">
+ <div className="line"></div>
+ <p className="divider-text">or</p>
+ </div>
+ <div className="linkPopup-document-search-container">
+ <i></i>
+ <input defaultValue={""} autoComplete="off" type="text" placeholder="Search for Document..." id="search-input"
+ className="linkPopup-searchBox searchBox-input" />
+
+ {/*
+ <SearchBox Document={CurrentUserUtils.MySearchPanelDoc}
+ DataDoc={CurrentUserUtils.MySearchPanelDoc}
+ fieldKey="data"
+ dropAction="move"
+ isSelected={returnTrue}
+ isContentActive={returnTrue}
+ select={returnTrue}
+ setHeight={returnFalse}
+ addDocument={undefined}
+ addDocTab={this.addDocTabFunc}
+ pinToPres={emptyFunction}
+ rootSelected={returnTrue}
+ styleProvider={DefaultStyleProvider}
+ layerProvider={undefined}
+ removeDocument={undefined}
+ ScreenToLocalTransform={Transform.Identity}
+ PanelWidth={this.getPWidth}
+ PanelHeight={this.getPHeight}
+ renderDepth={0}
+ focus={DocUtils.DefaultFocus}
+ docViewPath={returnEmptyDoclist}
+ whenChildContentsActiveChanged={emptyFunction}
+ bringToFront={emptyFunction}
+ docFilters={returnEmptyFilter}
+ docRangeFilters={returnEmptyFilter}
+ searchFilterDocs={returnEmptyDoclist}
+ ContainingCollectionView={undefined}
+ ContainingCollectionDoc={undefined} /> */}
+ </div>
+ </div>
+ );
+ }
+} \ 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<DocumentLinksButtonProps, {}> {
private _linkButton = React.createRef<HTMLDivElement>();
- @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<DocumentLinksButtonProp
public static invisibleWebRef = React.createRef<HTMLDivElement>();
@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<DocumentLinksButtonProp
if (DocumentLinksButton.StartLink === this.props.View.props.Document) {
DocumentLinksButton.StartLink = undefined;
DocumentLinksButton.StartLinkView = undefined;
- } else {
+ } else { //if this LinkButton's Document is undefined
DocumentLinksButton.StartLink = this.props.View.props.Document;
DocumentLinksButton.StartLinkView = this.props.View;
}
@@ -131,6 +132,7 @@ 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.StartLink) {
@@ -141,7 +143,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
} else if (DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document) {
const sourceDoc = DocumentLinksButton.StartLink;
const targetDoc = this.props.View.ComponentView?.getAnchor?.() || this.props.View.Document;
- const linkDoc = DocUtils.MakeLink({ doc: sourceDoc }, { doc: targetDoc }, "long drag");
+ const linkDoc = DocUtils.MakeLink({ doc: sourceDoc }, { doc: targetDoc }, "long drag"); //why is long drag here when this is used for completing links by clicking?
LinkManager.currentLink = linkDoc;
@@ -242,6 +244,9 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
return results;
}
+ /**
+ * gets the JSX of the link button (btn used to start/complete links) OR the link-view button (btn on bottom left of each linked node)
+ */
@computed get linkButtonInner() {
const btnDim = this.props.InMenu ? "20px" : "30px";
const link = <img style={{ width: "22px", height: "16px" }} src={`/assets/${"link.png"}`} />;
@@ -263,7 +268,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
: link
: Array.from(this.filteredLinks).length}
</div>
- {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
<div className={"documentLinksButton-endLink"}
style={{
width: btnDim, height: btnDim,
@@ -276,7 +281,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
onClick={e => 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
<div className={"documentLinksButton-startLink"} onPointerDown={this.clearLinks} onClick={this.clearLinks} style={{ width: btnDim, height: btnDim }} />
: (null)
}
@@ -290,6 +295,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
const buttonTitle = "Tap to view links; double tap to open link collection";
const title = this.props.InMenu ? menuTitle : buttonTitle;
+ //render circular tooltip if it isn't set to invisible and show the number of doc links the node has, and render inner-menu link button for starting/stopping links if currently in menu
return !Array.from(this.filteredLinks).length && !this.props.AlwaysOn ? (null) :
this.props.InMenu && (DocumentLinksButton.StartLink || this.props.StartLink) ?
<Tooltip title={<div className="dash-tooltip">{title}</div>}>
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<LinkDocPreviewProps> {
}
}
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<AntimodeMenuProps> {
@@ -38,6 +39,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
@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<AntimodeMenuProps> {
}
}
+ @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 =
<button className="antimodeMenu-button color-preview-button" title="" key="highlighter-button" onClick={this.highlightClicked}>
@@ -135,6 +145,13 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> {
<FontAwesomeIcon icon="comment-alt" size="lg" />
</button>
</Tooltip>,
+
+ <Tooltip key="link" title={<div className="dash-tooltip">{"Link selected text to document or URL"}</div>}>
+ <button className="antimodeMenu-button link" onPointerDown={this.toggleLinkPopup} style={{}}>
+ <FontAwesomeIcon icon="link" size="lg" />
+ </button>
+ </Tooltip>,
+ <LinkPopup showPopup={this._showLinkPopup} />
] : [
<Tooltip key="trash" title={<div className="dash-tooltip">{"Remove Link Anchor"}</div>}>
<button className="antimodeMenu-button" onPointerDown={this.Delete}>