From 30928b9bd3a90a04f5735e0ffbf92d0f74ad5d7d Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 9 Feb 2021 19:57:29 -0500 Subject: cleanup of formattedtextboxcomment and linkDocPreview --- src/client/views/nodes/LinkDocPreview.tsx | 36 +++++----- .../views/nodes/formattedText/FormattedTextBox.tsx | 10 ++- .../formattedText/FormattedTextBoxComment.scss | 10 ++- .../formattedText/FormattedTextBoxComment.tsx | 77 +++++++--------------- 4 files changed, 56 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 04a407eab..b1410e1f6 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -80,15 +80,17 @@ export class LinkDocPreview extends React.Component { } else { const anchorDoc = href.replace(Utils.prepend("/doc/"), "").split("?")[0]; anchorDoc && DocServer.GetRefField(anchorDoc).then(action(async anchor => { - if (anchor instanceof Doc) { + if (anchor instanceof Doc && DocListCast(anchor.links).length) { this._linkDoc = DocListCast(anchor.links)[0]; this._linkSrc = anchor; const targetanchor = LinkManager.getOppositeAnchor(this._linkDoc, this._linkSrc); runInAction(async () => { this._linkTarget = targetanchor; const target = this._linkTarget?.annotationOn ? await DocCastAsync(this._linkTarget.annotationOn) : this._linkTarget; - this._toolTipText = ""; - runInAction(() => this._targetDoc = target); + runInAction(() => { + this._toolTipText = ""; + this._targetDoc = target; + }); }); } })); @@ -99,8 +101,10 @@ export class LinkDocPreview extends React.Component { runInAction(async () => { this._linkTarget = Doc.AreProtosEqual(anchor1, linkSrc) || Doc.AreProtosEqual(anchor1.annotationOn as Doc, linkSrc) ? anchor2 : anchor1; const target = this._linkTarget?.annotationOn ? await DocCastAsync(this._linkTarget.annotationOn) : this._linkTarget; - this._toolTipText = ""; - runInAction(() => this._targetDoc = target); + runInAction(() => { + this._toolTipText = ""; + this._targetDoc = target; + }); }); } } @@ -125,22 +129,22 @@ export class LinkDocPreview extends React.Component { height = () => Math.min(225, NumCast(this._targetDoc?.[HeightSym](), 225)); @computed get previewHeader() { return !this._linkDoc || !this._targetDoc || !this._linkSrc ? (null) : -
-
+
+
{StrCast(this._targetDoc.title).length > 16 ? StrCast(this._targetDoc.title).substr(0, 16) + "..." : this._targetDoc.title} -

{StrCast(this._linkDoc.description)}

+

{StrCast(this._linkDoc.description)}

{(this.props.hrefs?.length || 0) <= 1 ? (null) : Next Link
} placement="top"> -
- +
+
} Delete Link
} placement="top"> -
- +
+
@@ -149,15 +153,15 @@ export class LinkDocPreview extends React.Component { @computed get docPreview() { return (!this._linkDoc || !this._targetDoc || !this._linkSrc) && !this._toolTipText ? (null) : -
+
{!this.props.showHeader ? (null) : this.previewHeader} -
+
{this._toolTipText ? this._toolTipText : { const targetanchor = LinkManager.getOppositeAnchor(this._linkDoc!, this._linkSrc!); targetanchor && this._targetDoc !== targetanchor && r?.focus(targetanchor); }} - Document={this._targetDoc} + Document={this._targetDoc!} moveDocument={returnFalse} rootSelected={returnFalse} styleProvider={this.props.docprops?.styleProvider} @@ -194,4 +198,4 @@ export class LinkDocPreview extends React.Component { {this.docPreview}
; } -} +} \ No newline at end of file diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index bf868634b..fece45e18 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -55,9 +55,8 @@ import { DocumentButtonBar } from '../../DocumentButtonBar'; import { AudioBox } from '../AudioBox'; import { FieldView, FieldViewProps } from "../FieldView"; import "./FormattedTextBox.scss"; -import { FormattedTextBoxComment, formattedTextBoxCommentPlugin, findLinkMark } from './FormattedTextBoxComment'; +import { FormattedTextBoxComment, findLinkMark } from './FormattedTextBoxComment'; import React = require("react"); -import { LinkManager } from '../../../util/LinkManager'; import { CollectionStackingView } from '../../collections/CollectionStackingView'; import { CollectionViewType } from '../../collections/CollectionView'; import { SnappingManager } from '../../../util/SnappingManager'; @@ -825,8 +824,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp props: { attributes: { class: "ProseMirror-example-setup-style" } } - }), - formattedTextBoxCommentPlugin + }), new Plugin({ view(editorView) { return new FormattedTextBoxComment(editorView); } }) ] }; } @@ -1613,8 +1611,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this.layoutDoc.limitHeight = undefined; this.layoutDoc._autoHeight = false; } - const nh = this.layoutDoc.isTemplateForField ? 0 : NumCast(this.layoutDoc._nativeHeight, 0); - const dh = NumCast(this.rootDoc._height, 0); + const nh = this.layoutDoc.isTemplateForField ? 0 : NumCast(this.layoutDoc._nativeHeight); + const dh = NumCast(this.rootDoc._height); const newHeight = Math.max(10, (nh ? dh / nh * scrollHeight : scrollHeight) + this.titleHeight); if (this.rootDoc !== this.layoutDoc.doc && !this.layoutDoc.resolvedDataDoc) { // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template. So set a timeout and hope its arrived... diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss b/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss index 3251319b9..55b8446e9 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.scss @@ -1,4 +1,4 @@ -.FormattedTextBox-tooltip { +.formattedTextBox-tooltip { position: absolute; pointer-events: all; height: 100%; @@ -14,9 +14,13 @@ max-width: 400; max-height: 235; height:max-content; + .formattedTextBox-tooltipText { + height: max-content; + text-overflow: ellipsis; + } } -.FormattedTextBox-tooltip:before { +.formattedTextBox-tooltip:before { content: ""; height: 0; width: 0; @@ -29,7 +33,7 @@ border-top-color: silver; } -.FormattedTextBox-tooltip:after { +.formattedTextBox-tooltip:after { content: ""; height: 0; width: 0; diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index 827bb2591..e4a1e0f1b 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -1,33 +1,19 @@ -import { action, observable } from "mobx"; import { Mark, ResolvedPos } from "prosemirror-model"; -import { EditorState, Plugin } from "prosemirror-state"; +import { EditorState } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; -import * as ReactDOM from 'react-dom'; -import { Doc, DocListCast, Opt } from "../../../../fields/Doc"; +import { Doc, DocListCast } from "../../../../fields/Doc"; import { Utils } from "../../../../Utils"; import { DocServer } from "../../../DocServer"; -import { Docs } from "../../../documents/Documents"; import { LinkDocPreview } from "../LinkDocPreview"; import { FormattedTextBox } from "./FormattedTextBox"; import './FormattedTextBoxComment.scss'; import { schema } from "./schema_rts"; -import React = require("react"); -export let formattedTextBoxCommentPlugin = new Plugin({ - view(editorView) { return new FormattedTextBoxComment(editorView); } -}); -export function findOtherUserMark(marks: Mark[]): Mark | undefined { - return marks.find(m => m.attrs.userid && m.attrs.userid !== Doc.CurrentUserEmail); -} -export function findUserMark(marks: Mark[]): Mark | undefined { - return marks.find(m => m.attrs.userid); -} -export function findLinkMark(marks: Mark[]): Mark | undefined { - return marks.find(m => m.type === schema.marks.linkAnchor); -} +export function findOtherUserMark(marks: Mark[]): Mark | undefined { return marks.find(m => m.attrs.userid && m.attrs.userid !== Doc.CurrentUserEmail); } +export function findUserMark(marks: Mark[]): Mark | undefined { return marks.find(m => m.attrs.userid); } +export function findLinkMark(marks: Mark[]): Mark | undefined { return marks.find(m => m.type === schema.marks.linkAnchor); } export function findStartOfMark(rpos: ResolvedPos, view: EditorView, finder: (marks: Mark[]) => Mark | undefined) { - let before = 0; - let nbef = rpos.nodeBefore; + let before = 0, nbef = rpos.nodeBefore; while (nbef && finder(nbef.marks)) { before += nbef.nodeSize; rpos = view.state.doc.resolve(rpos.pos - nbef.nodeSize); @@ -36,8 +22,7 @@ export function findStartOfMark(rpos: ResolvedPos, view: EditorView, finder: (ma return before; } export function findEndOfMark(rpos: ResolvedPos, view: EditorView, finder: (marks: Mark[]) => Mark | undefined) { - let after = 0; - let naft = rpos.nodeAfter; + let after = 0, naft = rpos.nodeAfter; while (naft && finder(naft.marks)) { after += naft.nodeSize; rpos = view.state.doc.resolve(rpos.pos + naft.nodeSize); @@ -49,7 +34,6 @@ export function findEndOfMark(rpos: ResolvedPos, view: EditorView, finder: (mark // this view appears when clicking on text that has a hyperlink which is configured to show a preview of its target. // this will also display metadata information about text when the view is configured to display things like other people who authored text. // - export class FormattedTextBoxComment { static tooltip: HTMLElement; static tooltipText: HTMLElement; @@ -60,14 +44,12 @@ export class FormattedTextBoxComment { constructor(view: any) { if (!FormattedTextBoxComment.tooltip) { - const root = document.getElementById("root"); FormattedTextBoxComment.tooltip = document.createElement("div"); - FormattedTextBoxComment.tooltipText = document.createElement("div"); - FormattedTextBoxComment.tooltipText.style.height = "max-content"; - FormattedTextBoxComment.tooltipText.style.textOverflow = "ellipsis"; - FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipText); FormattedTextBoxComment.tooltip.className = "FormattedTextBox-tooltip"; FormattedTextBoxComment.tooltip.style.display = "none"; + FormattedTextBoxComment.tooltipText = document.createElement("div"); + FormattedTextBoxComment.tooltipText.className = "FormattedTextBox-tooltipText"; + FormattedTextBoxComment.tooltip.appendChild(FormattedTextBoxComment.tooltipText); FormattedTextBoxComment.tooltip.onpointerdown = (e: PointerEvent) => { const textBox = FormattedTextBoxComment.textBox; false && FormattedTextBoxComment.start !== undefined && textBox?.adoptAnnotation( @@ -75,37 +57,34 @@ export class FormattedTextBoxComment { e.stopPropagation(); e.preventDefault(); }; - root?.appendChild(FormattedTextBoxComment.tooltip); + document.getElementById("root")?.appendChild(FormattedTextBoxComment.tooltip); } } public static Hide() { FormattedTextBoxComment.textBox = undefined; - FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = "none"); + FormattedTextBoxComment.tooltip.style.display = "none"; } public static SetState(textBox: any, start: number, end: number, mark: Mark) { FormattedTextBoxComment.textBox = textBox; FormattedTextBoxComment.start = start; FormattedTextBoxComment.end = end; FormattedTextBoxComment.mark = mark; - FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = ""); + FormattedTextBoxComment.tooltip.style.display = ""; } - @action static showCommentbox(set: string, view: EditorView, nbef: number) { const state = view.state; if (set !== "none") { // These are in screen coordinates - // let start = view.coordsAtPos(state.selection.from), end = view.coordsAtPos(state.selection.to); const start = view.coordsAtPos(state.selection.from - nbef), end = view.coordsAtPos(state.selection.from - nbef); // The box in which the tooltip is positioned, to use as base const box = (document.getElementsByClassName("mainView-container") as any)[0].getBoundingClientRect(); - // Find a center-ish x position from the selection endpoints (when - // crossing lines, end may be more to the left) + // Find a center-ish x position from the selection endpoints (when crossing lines, end may be more to the left) const left = Math.max((start.left + end.left) / 2, start.left + 3); FormattedTextBoxComment.tooltip.style.left = (left - box.left) + "px"; FormattedTextBoxComment.tooltip.style.bottom = (box.bottom - start.top) + "px"; } - FormattedTextBoxComment.tooltip && (FormattedTextBoxComment.tooltip.style.display = set); + FormattedTextBoxComment.tooltip.style.display = set; } static update(view: EditorView, lastState?: EditorState, hrefs: string = "") { @@ -139,33 +118,27 @@ export class FormattedTextBoxComment { const nbef = findStartOfMark(state.selection.$from, view, findLinkMark); const naft = findEndOfMark(state.selection.$from, view, findLinkMark) || nbef; let child: any = null; - state.doc.nodesBetween(state.selection.from, state.selection.to, (node: any, pos: number, parent: any) => !child && node.marks.length && (child = node)); + state.doc.nodesBetween(state.selection.from, state.selection.to, (node: any) => !child && node.marks.length && (child = node)); child = child || (nbef && state.selection.$from.nodeBefore); const mark = child ? findLinkMark(child.marks) : undefined; const href = (!mark?.attrs.docref || naft === nbef) && mark?.attrs.allAnchors.find((item: { href: string }) => item.href)?.href; if ((href && child && nbef && naft && mark?.attrs.showPreview)) { - const anchorDoc = href.indexOf(Utils.prepend("/doc/")) === 0 ? href.replace(Utils.prepend("/doc/"), "").split("?")[0] : undefined; - if (anchorDoc) { - DocServer.GetRefField(anchorDoc).then(async anchor => - anchor instanceof Doc && textBox && LinkDocPreview.SetLinkInfo({ - docprops: textBox.props.docViewPath.lastElement().props, - linkSrc: textBox.props.Document, - linkDoc: DocListCast(anchor.links)[0], - location: ((pos) => [pos.left, pos.top + 25])(view.coordsAtPos(state.selection.from - nbef)), - hrefs, - showHeader: true - }) - ); - } else if (hrefs?.length) { - LinkDocPreview.SetLinkInfo({ + const showPreview = (link?: Doc) => { + return LinkDocPreview.SetLinkInfo({ docprops: textBox.props.docViewPath.lastElement().props, linkSrc: textBox.props.Document, - linkDoc: undefined, + linkDoc: link, location: ((pos) => [pos.left, pos.top + 25])(view.coordsAtPos(state.selection.from - nbef)), hrefs, showHeader: true }); } + const anchorDoc = href.indexOf(Utils.prepend("/doc/")) === 0 ? href.replace(Utils.prepend("/doc/"), "").split("?")[0] : undefined; + if (anchorDoc) { + DocServer.GetRefField(anchorDoc).then(anchor => anchor instanceof Doc && showPreview(DocListCast(anchor.links)[0])); + } else if (hrefs?.length) { + showPreview() + } } } if (hide) FormattedTextBoxComment.Hide(); -- cgit v1.2.3-70-g09d2