aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/linking
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/linking')
-rw-r--r--src/client/views/linking/LinkEditor.scss40
-rw-r--r--src/client/views/linking/LinkEditor.tsx103
-rw-r--r--src/client/views/linking/LinkMenu.scss28
-rw-r--r--src/client/views/linking/LinkMenu.tsx8
-rw-r--r--src/client/views/linking/LinkMenuGroup.tsx23
-rw-r--r--src/client/views/linking/LinkMenuItem.scss20
-rw-r--r--src/client/views/linking/LinkPopup.scss45
-rw-r--r--src/client/views/linking/LinkPopup.tsx105
-rw-r--r--src/client/views/linking/LinkRelationshipSearch.tsx63
9 files changed, 374 insertions, 61 deletions
diff --git a/src/client/views/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss
index 7e6999cdc..abd413f57 100644
--- a/src/client/views/linking/LinkEditor.scss
+++ b/src/client/views/linking/LinkEditor.scss
@@ -1,4 +1,4 @@
-@import "../globalCssVariables";
+@import "../global/globalCssVariables";
.linkEditor {
width: 100%;
@@ -20,9 +20,9 @@
}
.linkEditor-info {
- //border-bottom: 0.5px solid $light-color-secondary;
+ //border-bottom: 0.5px solid $light-gray;
//padding-bottom: 1px;
- padding-top: 5px;
+ padding: 12px;
padding-left: 5px;
//margin-bottom: 6px;
display: flex;
@@ -61,7 +61,7 @@
}
.linkEditor-description {
- padding-left: 6.5px;
+ padding-left: 26px;
padding-right: 6.5px;
padding-bottom: 3.5px;
@@ -106,10 +106,28 @@
}
}
+.linkEditor-relationship-dropdown {
+ position: absolute;
+ width: 154px;
+ max-height: 90px;
+ overflow: auto;
+ background: white;
+
+ p {
+ padding: 3px;
+ cursor: pointer;
+ border: 1px solid $medium-gray;
+ }
+
+ p:hover {
+ background: $light-blue;
+ }
+}
+
.linkEditor-followingDropdown {
- padding-left: 6.5px;
+ padding-left: 26px;
padding-right: 6.5px;
- padding-bottom: 6px;
+ padding-bottom: 15px;
&:hover {
cursor: pointer;
@@ -195,7 +213,7 @@
}
.linkEditor-group {
- background-color: $light-color-secondary;
+ background-color: $light-gray;
padding: 6px;
margin: 3px 0;
border-radius: 3px;
@@ -254,8 +272,8 @@
}
.linkEditor-option {
- background-color: $light-color-secondary;
- border: 1px solid $intermediate-color;
+ background-color: $light-gray;
+ border: 1px solid $medium-gray;
border-top: 0;
padding: 3px;
cursor: pointer;
@@ -272,7 +290,7 @@
.linkEditor-typeButton {
background-color: transparent;
- color: $dark-color;
+ color: $dark-gray;
height: 20px;
padding: 0 3px;
padding-bottom: 2px;
@@ -285,7 +303,7 @@
width: calc(100% - 40px);
&:hover {
- background-color: $light-color;
+ background-color: $white;
}
}
diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx
index f74b422d3..240a71c3e 100644
--- a/src/client/views/linking/LinkEditor.tsx
+++ b/src/client/views/linking/LinkEditor.tsx
@@ -2,11 +2,12 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Tooltip } from "@material-ui/core";
import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
-import { Doc } from "../../../fields/Doc";
+import { Doc, StrListCast } from "../../../fields/Doc";
import { DateCast, StrCast } from "../../../fields/Types";
import { LinkManager } from "../../util/LinkManager";
import { undoBatch } from "../../util/UndoManager";
import './LinkEditor.scss';
+import { LinkRelationshipSearch } from "./LinkRelationshipSearch";
import React = require("react");
@@ -26,6 +27,8 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
@computed get infoIcon() { if (this.showInfo) { return "chevron-up"; } return "chevron-down"; }
@observable private buttonColor: string = "";
@observable private relationshipButtonColor: string = "";
+ @observable private relationshipSearchVisibility: string = "none";
+ @observable private searchIsActive: boolean = false;
//@observable description = this.props.linkDoc.description ? StrCast(this.props.linkDoc.description) : "DESCRIPTION";
@@ -39,12 +42,40 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
setRelationshipValue = action((value: string) => {
if (LinkManager.currentLink) {
LinkManager.currentLink.linkRelationship = value;
+ const linkRelationshipList = StrListCast(Doc.UserDoc().linkRelationshipList);
+ const linkColorList = StrListCast(Doc.UserDoc().linkColorList);
+ // if the relationship does not exist in the list, add it and a corresponding unique randomly generated color
+ if (linkRelationshipList && !linkRelationshipList.includes(value)) {
+ linkRelationshipList.push(value);
+ const randColor = "rgb(" + Math.floor(Math.random() * 255) + "," + Math.floor(Math.random() * 255) + "," + Math.floor(Math.random() * 255) + ")";
+ linkColorList.push(randColor);
+ }
this.relationshipButtonColor = "rgb(62, 133, 55)";
setTimeout(action(() => this.relationshipButtonColor = ""), 750);
return true;
}
});
+ /**
+ * returns list of strings with possible existing relationships that contain what is currently in the input field
+ */
+ @action
+ getRelationshipResults = () => {
+ const query = this.relationship; //current content in input box
+ const linkRelationshipList = StrListCast(Doc.UserDoc().linkRelationshipList);
+ if (linkRelationshipList) {
+ return linkRelationshipList.filter(rel => rel.includes(query));
+ }
+ }
+
+ /**
+ * toggles visibility of the relationship search results when the input field is focused on
+ */
+ @action
+ toggleRelationshipResults = () => {
+ this.relationshipSearchVisibility = this.relationshipSearchVisibility === "none" ? "block" : "none";
+ }
+
@undoBatch
setDescripValue = action((value: string) => {
if (LinkManager.currentLink) {
@@ -55,7 +86,7 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
}
});
- onKey = (e: React.KeyboardEvent<HTMLInputElement>) => {
+ onDescriptionKey = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter") {
this.setDescripValue(this.description);
document.getElementById('input')?.blur();
@@ -69,16 +100,38 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
}
}
- onDown = () => this.setDescripValue(this.description);
- onRelationshipDown = () => this.setRelationshipValue(this.description);
+ onDescriptionDown = () => this.setDescripValue(this.description);
+ onRelationshipDown = () => this.setRelationshipValue(this.relationship);
+
+ onBlur = () => {
+ //only hide the search results if the user clicks out of the input AND not on any of the search results
+ // i.e. if search is not active
+ if (!this.searchIsActive) {
+ this.toggleRelationshipResults();
+ }
+ }
+ onFocus = () => {
+ this.toggleRelationshipResults();
+ }
+ toggleSearchIsActive = () => {
+ this.searchIsActive = !this.searchIsActive;
+ }
@action
- handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { this.description = e.target.value; }
+ handleDescriptionChange = (e: React.ChangeEvent<HTMLInputElement>) => { this.description = e.target.value; }
@action
- handleRelationshipChange = (e: React.ChangeEvent<HTMLInputElement>) => { this.relationship = e.target.value; }
-
+ handleRelationshipChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+ this.relationship = e.target.value;
+ }
+ @action
+ handleRelationshipSearchChange = (result: string) => {
+ this.setRelationshipValue(result);
+ this.toggleRelationshipResults();
+ this.relationship = result;
+ }
@computed
get editRelationship() {
+ //NOTE: confusingly, the classnames for the following relationship JSX elements are the same as the for the description elements for shared CSS
return <div className="linkEditor-description">
<div className="linkEditor-description-label">Link Relationship:</div>
<div className="linkEditor-description-input">
@@ -87,11 +140,18 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
style={{ width: "100%" }}
id="input"
value={this.relationship}
- placeholder={"enter link label"}
- // color={"rgb(88, 88, 88)"}
+ placeholder={"Enter link relationship"}
onKeyDown={this.onRelationshipKey}
onChange={this.handleRelationshipChange}
+ onFocus={this.onFocus}
+ onBlur={this.onBlur}
></input>
+ <LinkRelationshipSearch
+ results={this.getRelationshipResults()}
+ display={this.relationshipSearchVisibility}
+ handleRelationshipSearchChange={this.handleRelationshipSearchChange}
+ toggleSearch={this.toggleSearchIsActive}
+ />
</div>
<div className="linkEditor-description-add-button"
style={{ background: this.relationshipButtonColor }}
@@ -110,15 +170,14 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
style={{ width: "100%" }}
id="input"
value={this.description}
- placeholder={"enter link label"}
- // color={"rgb(88, 88, 88)"}
- onKeyDown={this.onKey}
- onChange={this.handleChange}
+ placeholder={"Enter link description"}
+ onKeyDown={this.onDescriptionKey}
+ onChange={this.handleDescriptionChange}
></input>
</div>
<div className="linkEditor-description-add-button"
style={{ background: this.buttonColor }}
- onPointerDown={this.onDown}>Set</div>
+ onPointerDown={this.onDescriptionDown}>Set</div>
</div>
</div>;
}
@@ -149,35 +208,35 @@ export class LinkEditor extends React.Component<LinkEditorProps> {
<div className="linkEditor-followingDropdown-option"
onPointerDown={() => this.changeFollowBehavior("default")}>
Default
- </div>
+ </div>
<div className="linkEditor-followingDropdown-option"
onPointerDown={() => this.changeFollowBehavior("add:left")}>
Always open in new left pane
- </div>
+ </div>
<div className="linkEditor-followingDropdown-option"
onPointerDown={() => this.changeFollowBehavior("add:right")}>
Always open in new right pane
- </div>
+ </div>
<div className="linkEditor-followingDropdown-option"
onPointerDown={() => this.changeFollowBehavior("replace:right")}>
Always replace right tab
- </div>
+ </div>
<div className="linkEditor-followingDropdown-option"
onPointerDown={() => this.changeFollowBehavior("replace:left")}>
Always replace left tab
- </div>
+ </div>
<div className="linkEditor-followingDropdown-option"
onPointerDown={() => this.changeFollowBehavior("fullScreen")}>
Always open full screen
- </div>
+ </div>
<div className="linkEditor-followingDropdown-option"
onPointerDown={() => this.changeFollowBehavior("add")}>
Always open in a new tab
- </div>
+ </div>
<div className="linkEditor-followingDropdown-option"
onPointerDown={() => this.changeFollowBehavior("replace")}>
Replace Tab
- </div>
+ </div>
{this.props.linkDoc.linksToAnnotation ?
<div className="linkEditor-followingDropdown-option"
onPointerDown={() => this.changeFollowBehavior("openExternal")}>
diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss
index a90bf8b0a..19c6463d3 100644
--- a/src/client/views/linking/LinkMenu.scss
+++ b/src/client/views/linking/LinkMenu.scss
@@ -1,4 +1,4 @@
-@import "../globalCssVariables";
+@import "../global/globalCssVariables";
.linkMenu {
width: auto;
@@ -7,20 +7,19 @@
z-index: 2001;
.linkMenu-list,
- .linkMenu-listEditor
- {
+ .linkMenu-listEditor {
display: inline-block;
position: relative;
- border: 1px solid black;
- box-shadow: 3px 3px 1.5px grey;
+ border: 1px solid #e4e4e4;
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
background: white;
-
min-width: 170px;
- max-height: 170px;
+ max-height: 230px;
overflow-y: scroll;
z-index: 10;
- }
- .linkMenu-list {
+ }
+
+ .linkMenu-list {
white-space: nowrap;
overflow-x: hidden;
width: 240px;
@@ -46,13 +45,13 @@
}
.linkMenu-group-name {
+ padding: 10px;
&:hover {
- p {
- background-color: lightgray;
-
- }
+ // p {
+ // background-color: lightgray;
+ // }
p.expand-one {
width: calc(100% + 20px);
@@ -65,10 +64,9 @@
p {
width: 100%;
- //padding: 4px 6px;
line-height: 12px;
border-radius: 5px;
- font-weight: bold;
+ text-transform: capitalize;
}
.linkEditor-tableButton {
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
index c7888c5ee..53fe3f682 100644
--- a/src/client/views/linking/LinkMenu.tsx
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -15,6 +15,9 @@ interface Props {
changeFlyout: () => void;
}
+/**
+ * the outermost component for the link menu of a node that contains a list of its linked nodes
+ */
@observer
export class LinkMenu extends React.Component<Props> {
private _editorRef = React.createRef<HTMLDivElement>();
@@ -36,6 +39,11 @@ export class LinkMenu extends React.Component<Props> {
}
}
+ /**
+ * maps each link to a JSX element to be rendered
+ * @param groups containing info of all of the links
+ * @returns list of link JSX elements if there at least one linked element
+ */
renderAllGroups = (groups: Map<string, Array<Doc>>): Array<JSX.Element> => {
const linkItems = Array.from(groups.entries()).map(group =>
<LinkMenuGroup
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index 74af78234..cb6571f92 100644
--- a/src/client/views/linking/LinkMenuGroup.tsx
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -1,5 +1,5 @@
import { observer } from "mobx-react";
-import { Doc } from "../../../fields/Doc";
+import { Doc, StrListCast } from "../../../fields/Doc";
import { Id } from "../../../fields/FieldSymbols";
import { Cast } from "../../../fields/Types";
import { LinkManager } from "../../util/LinkManager";
@@ -20,6 +20,23 @@ interface LinkMenuGroupProps {
export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
private _menuRef = React.createRef<HTMLDivElement>();
+ getBackgroundColor = (): string => {
+ const linkRelationshipList = StrListCast(Doc.UserDoc().linkRelationshipList);
+ const linkColorList = StrListCast(Doc.UserDoc().linkColorList);
+ let color = "white";
+ // if this link's relationship property is not default "link", set its color
+ if (linkRelationshipList) {
+ const relationshipIndex = linkRelationshipList.indexOf(this.props.groupType);
+ const RGBcolor: string = linkColorList[relationshipIndex];
+ if (RGBcolor) {
+ //set opacity to 0.25 by modifiying the rgb string
+ color = RGBcolor.slice(0, RGBcolor.length - 1) + ", 0.25)";
+ console.log(color);
+ }
+ }
+ return color;
+ }
+
render() {
const set = new Set<Doc>(this.props.group);
const groupItems = Array.from(set.keys()).map(linkDoc => {
@@ -39,8 +56,8 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> {
return (
<div className="linkMenu-group" ref={this._menuRef}>
- <div className="linkMenu-group-name">
- <p className={this.props.groupType === "*" || this.props.groupType === "" ? "" : "expand-one"} > {this.props.groupType}:</p>
+ <div className="linkMenu-group-name" style={{ background: this.getBackgroundColor() }}>
+ <p className={this.props.groupType === "*" || this.props.groupType === "" ? "" : "expand-one"}> {this.props.groupType}:</p>
</div>
<div className="linkMenu-group-wrapper">
{groupItems}
diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss
index 4e13ef8c8..90722daf9 100644
--- a/src/client/views/linking/LinkMenuItem.scss
+++ b/src/client/views/linking/LinkMenuItem.scss
@@ -1,10 +1,10 @@
-@import "../globalCssVariables";
+@import "../global/globalCssVariables";
.linkMenu-item {
- // border-top: 0.5px solid $main-accent;
+ // border-top: 0.5px solid $medium-gray;
position: relative;
display: flex;
- border-bottom: 0.5px solid black;
+ border-top: 0.5px solid #cdcdcd;
padding-left: 6.5px;
padding-right: 2px;
@@ -55,8 +55,8 @@
.linkMenu-destination-title {
text-decoration: none;
- color: rgb(85, 120, 196);
- font-size: 14px;
+ color: #4476F7;
+ font-size: 16px;
padding-bottom: 2px;
padding-right: 4px;
margin-right: 4px;
@@ -76,7 +76,7 @@
text-decoration: none;
font-style: italic;
color: rgb(95, 97, 102);
- font-size: 10px;
+ font-size: 9px;
margin-left: 20px;
max-width: 125px;
height: auto;
@@ -102,7 +102,7 @@
.link-metadata {
padding: 0 10px 0 16px;
margin-bottom: 4px;
- color: $main-accent;
+ color: $medium-gray;
font-style: italic;
font-size: 10.5px;
}
@@ -143,8 +143,8 @@
padding-right: 6px;
border-radius: 50%;
pointer-events: auto;
- background-color: $dark-color;
- color: $light-color;
+ background-color: $dark-gray;
+ color: $white;
font-size: 65%;
transition: transform 0.2s;
text-align: center;
@@ -162,7 +162,7 @@
}
&:hover {
- background: $main-accent;
+ background: $medium-gray;
cursor: pointer;
}
}
diff --git a/src/client/views/linking/LinkPopup.scss b/src/client/views/linking/LinkPopup.scss
new file mode 100644
index 000000000..60c9ebfcd
--- /dev/null
+++ b/src/client/views/linking/LinkPopup.scss
@@ -0,0 +1,45 @@
+.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: 15px;
+ 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;
+ }
+ }
+
+
+ .searchBox-container {
+ background: pink;
+ }
+} \ 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..c8be9069c
--- /dev/null
+++ b/src/client/views/linking/LinkPopup.tsx
@@ -0,0 +1,105 @@
+import { action, observable } from 'mobx';
+import { observer } from "mobx-react";
+import { EditorView } from 'prosemirror-view';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../Utils';
+import { DocUtils } from '../../documents/Documents';
+import { CurrentUserUtils } from '../../util/CurrentUserUtils';
+import { Transform } from '../../util/Transform';
+import { undoBatch } from '../../util/UndoManager';
+import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
+import { SearchBox } from '../search/SearchBox';
+import { DefaultStyleProvider } from '../StyleProvider';
+import './LinkPopup.scss';
+import React = require("react");
+import { Doc, Opt } from '../../../fields/Doc';
+
+interface LinkPopupProps {
+ showPopup: boolean;
+ linkFrom?: () => Doc | undefined;
+ // 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> {
+ @observable private linkURL: string = "";
+ @observable public view?: EditorView;
+
+
+
+ // TODO: should check for valid URL
+ @undoBatch
+ makeLinkToURL = (target: string, lcoation: string) => {
+ ((this.view as any)?.TextView as FormattedTextBox).makeLinkAnchor(undefined, "onRadd:rightight", target, target);
+ }
+
+ @action
+ onLinkChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+ this.linkURL = e.target.value;
+ }
+
+
+ getPWidth = () => 500;
+ getPHeight = () => 500;
+
+ render() {
+ const popupVisibility = this.props.showPopup ? "block" : "none";
+ const linkDoc = this.props.linkFrom ? this.props.linkFrom : undefined;
+ return (
+ <div className="linkPopup-container" style={{ display: popupVisibility }}>
+ {/* <div className="linkPopup-url-container">
+ <input autoComplete="off" type="text" value={this.linkURL} placeholder="Enter URL..." onChange={this.onLinkChange} />
+ <button onPointerDown={e => this.makeLinkToURL(this.linkURL, "add:right")}
+ 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}
+ linkFrom={linkDoc}
+ linkSearch={true}
+ fieldKey="data"
+ dropAction="move"
+ isSelected={returnTrue}
+ isContentActive={returnTrue}
+ select={returnTrue}
+ setHeight={returnFalse}
+ addDocument={undefined}
+ addDocTab={returnTrue}
+ 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/linking/LinkRelationshipSearch.tsx b/src/client/views/linking/LinkRelationshipSearch.tsx
new file mode 100644
index 000000000..53da880e4
--- /dev/null
+++ b/src/client/views/linking/LinkRelationshipSearch.tsx
@@ -0,0 +1,63 @@
+import { observer } from "mobx-react";
+import './LinkEditor.scss';
+import React = require("react");
+
+interface LinkRelationshipSearchProps {
+ results: string[] | undefined;
+ display: string;
+ //callback fn to set rel + hide dropdown upon setting
+ handleRelationshipSearchChange: (result: string) => void;
+ toggleSearch: () => void;
+}
+@observer
+export class LinkRelationshipSearch extends React.Component<LinkRelationshipSearchProps> {
+
+ handleResultClick = (e: React.MouseEvent) => {
+ const relationship = (e.target as HTMLParagraphElement).textContent;
+ if (relationship) {
+ this.props.handleRelationshipSearchChange(relationship);
+ }
+ }
+
+ handleMouseEnter = () => {
+ this.props.toggleSearch();
+ }
+
+ handleMouseLeave = () => {
+ this.props.toggleSearch();
+ }
+
+ /**
+ * Render an empty div to increase the height of LinkEditor to accommodate 2+ results
+ */
+ emptyDiv = () => {
+ if (this.props.results && this.props.results.length > 2 && this.props.display === "block") {
+ return <div style={{ height: "50px" }} />;
+ }
+ }
+
+ render() {
+ return (
+ <div className="linkEditor-relationship-dropdown-container">
+ <div className="linkEditor-relationship-dropdown"
+ style={{ display: this.props.display }}
+ onMouseEnter={this.handleMouseEnter}
+ onMouseLeave={this.handleMouseLeave}
+ >
+ { // return a dropdown of relationship results if there exist results
+ this.props.results
+ ? this.props.results.map(result => {
+ return <p key={result} onClick={this.handleResultClick}>
+ {result}
+ </p>;
+ })
+ : <p>No matching relationships</p>
+ }
+ </div>
+
+ {/*Render an empty div to increase the height of LinkEditor to accommodate 2+ results */}
+ {this.emptyDiv()}
+ </div>
+ );
+ }
+} \ No newline at end of file