diff options
Diffstat (limited to 'src/client/views/linking')
| -rw-r--r-- | src/client/views/linking/LinkEditor.scss | 94 | ||||
| -rw-r--r-- | src/client/views/linking/LinkEditor.tsx | 104 | ||||
| -rw-r--r-- | src/client/views/linking/LinkMenu.scss | 24 | ||||
| -rw-r--r-- | src/client/views/linking/LinkMenu.tsx | 30 | ||||
| -rw-r--r-- | src/client/views/linking/LinkMenuGroup.tsx | 6 | ||||
| -rw-r--r-- | src/client/views/linking/LinkMenuItem.scss | 53 | ||||
| -rw-r--r-- | src/client/views/linking/LinkMenuItem.tsx | 36 |
7 files changed, 295 insertions, 52 deletions
diff --git a/src/client/views/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss index b47c8976e..406a38c26 100644 --- a/src/client/views/linking/LinkEditor.scss +++ b/src/client/views/linking/LinkEditor.scss @@ -7,34 +7,112 @@ user-select: none; } -.linkEditor-back { +.linkEditor-button-back { margin-bottom: 6px; + border-radius: 10px; + width: 18px; + height: 18px; + padding: 0; } .linkEditor-info { - border-bottom: 0.5px solid $light-color-secondary; - padding-bottom: 6px; - margin-bottom: 6px; + //border-bottom: 0.5px solid $light-color-secondary; + padding-bottom: 4px; + padding-top: 5px; + padding-left: 5px; + //margin-bottom: 6px; display: flex; justify-content: space-between; .linkEditor-linkedTo { width: calc(100% - 26px); + padding-left: 5px; + padding-right: 5px } } -.linkEditor-button, .linkEditor-addbutton { +.linkEditor-description { + padding-left: 6.5px; + padding-right: 6.5px; + padding-bottom: 3.5px; + + .linkEditor-description-text { + text-decoration-color: grey; + } + + .linkEditor-description-input { + border: 1px solid grey; + border-radius: 4px; + background-color: rgb(236, 236, 236); + padding-left: 2px; + padding-right: 2px; + color: grey; + text-decoration-color: grey; + } +} + +.linkEditor-followingDropdown { + padding-left: 6.5px; + padding-right: 6.5px; + padding-bottom: 3.5px; + + .linkEditor-followingDropdown-dropdown { + + .linkEditor-followingDropdown-header { + + border: 1px solid grey; + border-radius: 4px; + background-color: rgb(236, 236, 236); + padding-left: 2px; + padding-right: 2px; + color: grey; + text-decoration-color: grey; + + .linkEditor-followingDropdown-icon { + float: right; + } + } + + .linkEditor-followingDropdown-optionsList { + padding-left: 3px; + padding-right: 3px; + + .linkEditor-followingDropdown-option { + border: 0.25px dotted grey; + background-color: rgb(236, 236, 236); + padding-left: 2px; + padding-right: 2px; + color: grey; + text-decoration-color: grey; + font-size: 9px; + + &:hover { + background-color: rgb(211, 210, 210); + } + } + + } + } + + +} + + +.linkEditor-button, +.linkEditor-addbutton { width: 18px; height: 18px; padding: 0; // font-size: 12px; border-radius: 10px; + &:disabled { background-color: gray; } } -.linkEditor-addbutton{ + +.linkEditor-addbutton { margin-left: 0px; } @@ -44,7 +122,7 @@ } .linkEditor-group { - background-color: $light-color-secondary; + background-color: $light-color-secondary; padding: 6px; margin: 3px 0; border-radius: 3px; @@ -56,7 +134,7 @@ .linkEditor-group-row-label { margin-right: 6px; - display:inline-block; + display: inline-block; } .linkEditor-metadata-row { diff --git a/src/client/views/linking/LinkEditor.tsx b/src/client/views/linking/LinkEditor.tsx index 13b9a2459..014d57ed0 100644 --- a/src/client/views/linking/LinkEditor.tsx +++ b/src/client/views/linking/LinkEditor.tsx @@ -1,14 +1,18 @@ import { library } from "@fortawesome/fontawesome-svg-core"; import { faArrowLeft, faCog, faEllipsisV, faExchangeAlt, faPlus, faTable, faTimes, faTrash } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, observable } from "mobx"; +import { action, observable, computed } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../../fields/Doc"; +import { Doc, Opt } from "../../../fields/Doc"; import { StrCast } from "../../../fields/Types"; import { Utils } from "../../../Utils"; import { LinkManager } from "../../util/LinkManager"; import './LinkEditor.scss'; import React = require("react"); +import { DocumentView } from "../nodes/DocumentView"; +import { DocumentLinksButton } from "../nodes/DocumentLinksButton"; +import { EditableView } from "../EditableView"; +import { RefObject } from "react"; library.add(faArrowLeft, faEllipsisV, faTable, faTrash, faCog, faExchangeAlt, faTimes, faPlus); @@ -281,27 +285,113 @@ interface LinkEditorProps { @observer export class LinkEditor extends React.Component<LinkEditorProps> { + + @observable description = StrCast(LinkManager.currentLink?.description); + @observable openDropdown: boolean = false; + + @observable followBehavior = this.props.linkDoc.follow ? this.props.linkDoc.follow : "Default"; + + + //@observable description = this.props.linkDoc.description ? StrCast(this.props.linkDoc.description) : "DESCRIPTION"; + @action deleteLink = (): void => { LinkManager.Instance.deleteLink(this.props.linkDoc); this.props.showLinks(); } + @action + setDescripValue = (value: string) => { + if (LinkManager.currentLink) { + LinkManager.currentLink.description = value; + return true; + } + } + + @computed + get editDescription() { + return <div className="linkEditor-description"> + <div className="linkEditor-description-label"> + Link Description:</div> + <div className="linkEditor-description-input"> + <EditableView + GetValue={() => StrCast(LinkManager.currentLink?.description)} + SetValue={value => { this.setDescripValue(value); return false; }} + contents={LinkManager.currentLink?.description} + placeholder={"(optional) enter link description"} + color={"rgb(88, 88, 88)"} + ></EditableView></div></div>; + } + + @action + changeDropdown = () => { + this.openDropdown = !this.openDropdown; + } + + @action + changeFollowBehavior = (follow: string) => { + this.openDropdown = false; + this.followBehavior = follow; + this.props.linkDoc.follow = follow; + } + + @computed + get followingDropdown() { + return <div className="linkEditor-followingDropdown"> + <div className="linkEditor-followingDropdown-label"> + Follow Behavior:</div> + <div className="linkEditor-followingDropdown-dropdown"> + <div className="linkEditor-followingDropdown-header" + onPointerDown={this.changeDropdown}> + {this.followBehavior} + <FontAwesomeIcon className="linkEditor-followingDropdown-icon" + icon={this.openDropdown ? "chevron-up" : "chevron-down"} + size={"lg"} onPointerDown={this.changeDropdown} /> + </div> + <div className="linkEditor-followingDropdown-optionsList" + style={{ display: this.openDropdown ? "" : "none" }}> + <div className="linkEditor-followingDropdown-option" + onPointerDown={() => this.changeFollowBehavior("Default")}> + Default + </div> + <div className="linkEditor-followingDropdown-option" + onPointerDown={() => this.changeFollowBehavior("Always open in right tab")}> + Always open in right tab + </div> + <div className="linkEditor-followingDropdown-option" + onPointerDown={() => this.changeFollowBehavior("Always open in new tab")}> + Always open in new tab + </div> + </div> + </div> + </div>; + } + render() { const destination = LinkManager.Instance.getOppositeAnchor(this.props.linkDoc, this.props.sourceDoc); const groups = [this.props.linkDoc].map(groupDoc => { - return <LinkGroupEditor key={"gred-" + StrCast(groupDoc.linkRelationship)} linkDoc={this.props.linkDoc} sourceDoc={this.props.sourceDoc} groupDoc={groupDoc} />; + return <LinkGroupEditor key={"gred-" + StrCast(groupDoc.linkRelationship)} linkDoc={this.props.linkDoc} + sourceDoc={this.props.sourceDoc} groupDoc={groupDoc} />; }); return !destination ? (null) : ( <div className="linkEditor"> - {this.props.hideback ? (null) : <button className="linkEditor-back" onPointerDown={() => this.props.showLinks()}><FontAwesomeIcon icon="arrow-left" size="sm" /></button>} <div className="linkEditor-info"> - <p className="linkEditor-linkedTo">editing link to: <b>{destination.proto?.title ?? destination.title ?? "untitled"}</b></p> - <button className="linkEditor-button" onPointerDown={() => this.deleteLink()} title="Delete link"><FontAwesomeIcon icon="trash" size="sm" /></button> + <button className="linkEditor-button-back" + style={{ display: this.props.hideback ? "none" : "" }} + onClick={this.props.showLinks}> + <FontAwesomeIcon icon="arrow-left" size="sm" /> </button> + <p className="linkEditor-linkedTo">editing link to: <b>{ + destination.proto?.title ?? destination.title ?? "untitled"}</b></p> + <button className="linkEditor-button" onPointerDown={() => this.deleteLink()} title="Delete link"> + <FontAwesomeIcon icon="trash" size="sm" /></button> </div> - {groups.length > 0 ? groups : <div className="linkEditor-group">There are currently no relationships associated with this link.</div>} + + <div>{this.editDescription}</div> + <div>{this.followingDropdown}</div> + + {/* {groups.length > 0 ? groups : <div className="linkEditor-group">There are currently no relationships associated with this link.</div>} */} </div> ); diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss index 6468ccd3d..4b1a3f425 100644 --- a/src/client/views/linking/LinkMenu.scss +++ b/src/client/views/linking/LinkMenu.scss @@ -3,20 +3,32 @@ .linkMenu { width: 100%; height: auto; + //border: 1px solid black; + + &:hover { + width: calc(auto + 26px); + } } .linkMenu-list { + border: 1px solid black; max-height: 200px; overflow-y: scroll; position: absolute; z-index: 10; - background: $link-color; - min-width: 150px + background: white; + min-width: 150px; + border-radius: 5px; + padding-top: 6.5px; + padding-bottom: 6.5px; + padding-left: 6.5px; + padding-right: 2px; + //width: calc(auto + 50px); } .linkMenu-group { - border-bottom: 0.5px solid lightgray; - padding: 5px 0; + //border-bottom: 0.5px solid lightgray; + //@extend: 5px 0; &:last-child { @@ -26,13 +38,15 @@ .linkMenu-group-name { display: flex; + &:hover { p { background-color: lightgray; + } p.expand-one { - width: calc(100% - 26px); + width: calc(100% + 26px); } .linkEditor-tableButton { diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index c672511ac..8a7b12f48 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -11,6 +11,7 @@ import { faTrash } from '@fortawesome/free-solid-svg-icons'; import { library } from "@fortawesome/fontawesome-svg-core"; import { DocumentLinksButton } from "../nodes/DocumentLinksButton"; import { LinkDocPreview } from "../nodes/LinkDocPreview"; +import { isUndefined } from "util"; library.add(faTrash); @@ -25,19 +26,20 @@ interface Props { export class LinkMenu extends React.Component<Props> { @observable private _editingLink?: Doc; - @observable private _linkMenuRef: Opt<HTMLDivElement | null>; + @observable private _linkMenuRef = React.createRef<HTMLDivElement>(); + private _editorRef = React.createRef<HTMLDivElement>(); @action onClick = (e: PointerEvent) => { LinkDocPreview.LinkInfo = undefined; - if (this._linkMenuRef?.contains(e.target as any)) { - DocumentLinksButton.EditLink = undefined; - } - if (this._linkMenuRef && !this._linkMenuRef.contains(e.target as any)) { - DocumentLinksButton.EditLink = undefined; + if (this._linkMenuRef && !!!this._linkMenuRef.current?.contains(e.target as any)) { + if (this._editorRef && !!!this._editorRef.current?.contains(e.target as any)) { + console.log("outside click"); + DocumentLinksButton.EditLink = undefined; + } } } @action @@ -78,12 +80,14 @@ export class LinkMenu extends React.Component<Props> { render() { const sourceDoc = this.props.docView.props.Document; const groups: Map<string, Doc[]> = LinkManager.Instance.getRelatedGroupedLinks(sourceDoc); - return <div className="linkMenu-list" - ref={(r) => this._linkMenuRef = r} style={{ left: this.props.location[0], top: this.props.location[1] }}> - {!this._editingLink ? - this.renderAllGroups(groups) : - <LinkEditor sourceDoc={this.props.docView.props.Document} linkDoc={this._editingLink} showLinks={action(() => this._editingLink = undefined)} /> - } - </div>; + return <div className="linkMenu" ref={this._linkMenuRef} > + <div className="linkMenu-list" + style={{ left: this.props.location[0], top: this.props.location[1] }}> + {!this._editingLink ? + this.renderAllGroups(groups) : + <LinkEditor sourceDoc={this.props.docView.props.Document} linkDoc={this._editingLink} + showLinks={action(() => this._editingLink = undefined)} /> + } + </div> </div>; } }
\ No newline at end of file diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index 7892d381b..ec17776e3 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -26,6 +26,7 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> { private _drag = React.createRef<HTMLDivElement>(); private _table = React.createRef<HTMLDivElement>(); + private _menuRef = React.createRef<HTMLDivElement>(); onLinkButtonDown = (e: React.PointerEvent): void => { e.stopPropagation(); @@ -74,12 +75,13 @@ export class LinkMenuGroup extends React.Component<LinkMenuGroupProps> { linkDoc={linkDoc} sourceDoc={this.props.sourceDoc} destinationDoc={destination} - showEditor={this.props.showEditor} />; + showEditor={this.props.showEditor} + menuRef={this._menuRef} />; } }); return ( - <div className="linkMenu-group"> + <div className="linkMenu-group" ref={this._menuRef}> {/* <div className="linkMenu-group-name"> <p ref={this._drag} onPointerDown={this.onLinkButtonDown} className={this.props.groupType === "*" || this.props.groupType === "" ? "" : "expand-one"} > {this.props.groupType}:</p> diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss index e3ce69cd7..67bf71fb9 100644 --- a/src/client/views/linking/LinkMenuItem.scss +++ b/src/client/views/linking/LinkMenuItem.scss @@ -4,19 +4,39 @@ // border-top: 0.5px solid $main-accent; position: relative; display: flex; - font-size: 12px; .linkMenu-name { position: relative; - p { - padding: 4px 6px; - line-height: 12px; - border-radius: 5px; - overflow-wrap: break-word; - user-select: none; + .linkMenu-text { + + padding: 4px 2px; + //display: inline; + + .linkMenu-destination-title { + text-decoration: none; + color: rgb(85, 120, 196); + font-size: 14px; + padding-bottom: 2px; + } + + .linkMenu-description { + text-decoration: none; + font-style: italic; + color: rgb(95, 97, 102); + font-size: 10px; + } + + p { + //padding: 4px 2px; + line-height: 12px; + border-radius: 5px; + overflow-wrap: break-word; + user-select: none; + } } + } .linkMenu-item-content { @@ -32,25 +52,40 @@ } &:hover { + + .linkMenu-item-buttons { display: flex; } .linkMenu-item-content { + + .linkMenu-destination-title { + text-decoration: underline; + color: rgb(60, 90, 156); + //display: inline; + text-overflow: break; + } + &.expand-two p { width: calc(100% - 52px); - background-color: lightgray; + //text-decoration: underline; + //color: rgb(15, 57, 148); + //background-color: lightgray; } &.expand-three p { width: calc(100% - 84px); - background-color: lightgray; + //text-decoration: underline; + //color: rgb(15, 57, 148); + //background-color: lightgray; } } } } .linkMenu-item-buttons { + //@extend: right; position: absolute; top: 50%; right: 0; diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 04cd83ee0..6af474513 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -26,6 +26,7 @@ interface LinkMenuItemProps { destinationDoc: Doc; showEditor: (linkDoc: Doc) => void; addDocTab: (document: Doc, where: string) => boolean; + menuRef: React.Ref<HTMLDivElement>; } // drag links and drop link targets (aliasing them if needed) @@ -77,6 +78,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { @action toggleShowMore(e: React.PointerEvent) { e.stopPropagation(); this._showMore = !this._showMore; } onEdit = (e: React.PointerEvent): void => { + LinkManager.currentLink = this.props.linkDoc; setupMoveUpEvents(this, e, this.editMoved, emptyFunction, () => this.props.showEditor(this.props.linkDoc)); } @@ -110,7 +112,8 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { document.removeEventListener("pointerup", this.onLinkButtonUp); document.addEventListener("pointerup", this.onLinkButtonUp); - if (this._buttonRef && this._buttonRef.current?.contains(e.target as any)) { + if (this._buttonRef && !!!this._buttonRef.current?.contains(e.target as any)) { + console.log("outside click"); LinkDocPreview.LinkInfo = undefined; } } @@ -147,7 +150,18 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { console.log("FOLLOWWW"); DocumentLinksButton.EditLink = undefined; LinkDocPreview.LinkInfo = undefined; - DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.sourceDoc, doc => this.props.addDocTab(doc, "onRight"), false); + + if (this.props.linkDoc.follow) { + if (this.props.linkDoc.follow === "Default") { + DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.sourceDoc, doc => this.props.addDocTab(doc, "onRight"), false); + } else if (this.props.linkDoc.follow === "Always open in right tab") { + this.props.addDocTab(this.props.destinationDoc, "onRight"); + } else if (this.props.linkDoc.follow === "Always open in new tab") { + this.props.addDocTab(this.props.destinationDoc, "inTab"); + } + } else { + DocumentManager.Instance.FollowLink(this.props.linkDoc, this.props.sourceDoc, doc => this.props.addDocTab(doc, "onRight"), false); + } } @action @@ -174,18 +188,24 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { Location: [e.clientX, e.clientY + 20] }))} onPointerDown={this.onLinkButtonDown}> - <p >{StrCast(this.props.destinationDoc.title)}</p> + + <div className="linkMenu-text"> + <p className="linkMenu-destination-title" + onPointerDown={this.followDefault}> + {StrCast(this.props.destinationDoc.title)}</p> + {this.props.linkDoc.description !== "" ? <p className="linkMenu-description"> + {StrCast(this.props.linkDoc.description)}</p> : null} </div> + <div className="linkMenu-item-buttons" ref={this._buttonRef} > {canExpand ? <div title="Show more" className="button" onPointerDown={e => this.toggleShowMore(e)}> <FontAwesomeIcon className="fa-icon" icon={this._showMore ? "chevron-up" : "chevron-down"} size="sm" /></div> : <></>} - {/* <div title="Edit link" className="button" ref={this._editRef} onPointerDown={this.onEdit}> - <FontAwesomeIcon className="fa-icon" icon="pencil-alt" size="sm" /></div> */} + <div title="Edit link" className="button" ref={this._editRef} onPointerDown={this.onEdit}> + <FontAwesomeIcon className="fa-icon" icon="edit" size="sm" /></div> <div title="Delete link" className="button" onPointerDown={this.deleteLink}> <FontAwesomeIcon className="fa-icon" icon="trash" size="sm" /></div> - <div title="Follow link" className="button" onPointerDown={this.followDefault} onContextMenu={this.onContextMenu}> - <FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /> - </div> + {/* <div title="Follow link" className="button" onPointerDown={this.followDefault} onContextMenu={this.onContextMenu}> + <FontAwesomeIcon className="fa-icon" icon="arrow-right" size="sm" /></div> */} </div> </div> {this._showMore ? this.renderMetadata() : <></>} |
