diff options
Diffstat (limited to 'src/client/views/nodes/formattedText')
6 files changed, 142 insertions, 118 deletions
diff --git a/src/client/views/nodes/formattedText/DashDocCommentView.tsx b/src/client/views/nodes/formattedText/DashDocCommentView.tsx index fcd6e0c55..aa269d8d6 100644 --- a/src/client/views/nodes/formattedText/DashDocCommentView.tsx +++ b/src/client/views/nodes/formattedText/DashDocCommentView.tsx @@ -32,7 +32,7 @@ export class DashDocCommentView { }; this.root = ReactDOM.createRoot(this.dom); - this.root.render(<DashDocCommentViewInternal view={view} getPos={getPos} docid={node.attrs.docid} />); + this.root.render(<DashDocCommentViewInternal view={view} getPos={getPos} docId={node.attrs.docId} />); (this as any).dom = this.dom; } @@ -48,7 +48,7 @@ export class DashDocCommentView { } interface IDashDocCommentViewInternal { - docid: string; + docId: string; view: any; getPos: any; } @@ -63,13 +63,13 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV } onPointerLeaveCollapsed(e: any) { - DocServer.GetRefField(this.props.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowUnhighlight()); + DocServer.GetRefField(this.props.docId).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowUnhighlight()); e.preventDefault(); e.stopPropagation(); } onPointerEnterCollapsed(e: any) { - DocServer.GetRefField(this.props.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc, false)); + DocServer.GetRefField(this.props.docId).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc, false)); e.preventDefault(); e.stopPropagation(); } @@ -82,7 +82,7 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV const tr = this.props.view.state.tr.setNodeMarkup(target.pos, undefined, { ...target.node.attrs, hidden: target.node.attrs.hidden ? false : true }); this.props.view.dispatch(tr.setSelection(TextSelection.create(tr.doc, this.props.getPos() + (expand ? 2 : 1)))); // update the attrs setTimeout(() => { - expand && DocServer.GetRefField(this.props.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)); + expand && DocServer.GetRefField(this.props.docId).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc)); try { this.props.view.dispatch(this.props.view.state.tr.setSelection(TextSelection.create(this.props.view.state.tr.doc, this.props.getPos() + (expand ? 2 : 1)))); } catch (e) {} @@ -100,12 +100,12 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV const state = this.props.view.state; for (let i = this.props.getPos() + 1; i < state.doc.content.size; i++) { const m = state.doc.nodeAt(i); - if (m && m.type === state.schema.nodes.dashDoc && m.attrs.docid === this.props.docid) { + if (m && m.type === state.schema.nodes.dashDoc && m.attrs.docId === this.props.docId) { return { node: m, pos: i, hidden: m.attrs.hidden } as { node: any; pos: number; hidden: boolean }; } } - const dashDoc = state.schema.nodes.dashDoc.create({ width: 75, height: 35, title: 'dashDoc', docid: this.props.docid, float: 'right' }); + const dashDoc = state.schema.nodes.dashDoc.create({ width: 75, height: 35, title: 'dashDoc', docId: this.props.docId, float: 'right' }); this.props.view.dispatch(state.tr.insert(this.props.getPos() + 1, dashDoc)); setTimeout(() => { try { @@ -119,7 +119,7 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV return ( <span className="formattedTextBox-inlineComment" - id={'DashDocCommentView-' + this.props.docid} + id={'DashDocCommentView-' + this.props.docId} onPointerLeave={this.onPointerLeaveCollapsed} onPointerEnter={this.onPointerEnterCollapsed} onPointerUp={this.onPointerUpCollapsed} diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx index 19ee1fc7b..b31fc01ff 100644 --- a/src/client/views/nodes/formattedText/DashDocView.tsx +++ b/src/client/views/nodes/formattedText/DashDocView.tsx @@ -9,10 +9,9 @@ import { DocServer } from '../../../DocServer'; import { Docs, DocUtils } from '../../../documents/Documents'; import { ColorScheme } from '../../../util/SettingsManager'; import { Transform } from '../../../util/Transform'; -import { DocumentView } from '../DocumentView'; +import { DocFocusOptions, DocumentView } from '../DocumentView'; import { FormattedTextBox } from './FormattedTextBox'; import React = require('react'); -import { SelectionManager } from '../../../util/SelectionManager'; export class DashDocView { dom: HTMLSpanElement; // container for label and value @@ -42,7 +41,7 @@ export class DashDocView { this.root = ReactDOM.createRoot(this.dom); this.root.render( - <DashDocViewInternal docid={node.attrs.docid} alias={node.attrs.alias} width={node.attrs.width} height={node.attrs.height} hidden={node.attrs.hidden} fieldKey={node.attrs.fieldKey} tbox={tbox} view={view} node={node} getPos={getPos} /> + <DashDocViewInternal docId={node.attrs.docId} alias={node.attrs.alias} width={node.attrs.width} height={node.attrs.height} hidden={node.attrs.hidden} fieldKey={node.attrs.fieldKey} tbox={tbox} view={view} node={node} getPos={getPos} /> ); } destroy() { @@ -53,7 +52,7 @@ export class DashDocView { } interface IDashDocViewInternal { - docid: string; + docId: string; alias: string; tbox: FormattedTextBox; width: string; @@ -77,7 +76,7 @@ export class DashDocViewInternal extends React.Component<IDashDocViewInternal> { updateDoc = action((dashDoc: Doc) => { this._dashDoc = dashDoc; - this._finalLayout = this.props.docid ? dashDoc : Doc.expandTemplateLayout(Doc.Layout(dashDoc), dashDoc, this.props.fieldKey); + this._finalLayout = this.props.docId ? dashDoc : Doc.expandTemplateLayout(Doc.Layout(dashDoc), dashDoc); if (this._finalLayout) { if (!Doc.AreProtosEqual(this._finalLayout, dashDoc)) { @@ -107,12 +106,12 @@ export class DashDocViewInternal extends React.Component<IDashDocViewInternal> { super(props); this._textBox = this.props.tbox; - DocServer.GetRefField(this.props.docid + this.props.alias).then(async dashDoc => { + DocServer.GetRefField(this.props.docId + this.props.alias).then(async dashDoc => { if (!(dashDoc instanceof Doc)) { this.props.alias && - DocServer.GetRefField(this.props.docid).then(async dashDocBase => { + DocServer.GetRefField(this.props.docId).then(async dashDocBase => { if (dashDocBase instanceof Doc) { - const aliasedDoc = Doc.MakeAlias(dashDocBase, this.props.docid + this.props.alias); + const aliasedDoc = Doc.MakeAlias(dashDocBase, this.props.docId + this.props.alias); aliasedDoc.layoutKey = 'layout'; this.props.fieldKey && DocUtils.makeCustomViewClicked(aliasedDoc, Docs.Create.StackingDocument, this.props.fieldKey, undefined); this.updateDoc(aliasedDoc); @@ -151,7 +150,7 @@ export class DashDocViewInternal extends React.Component<IDashDocViewInternal> { const { scale, translateX, translateY } = Utils.GetScreenTransform(this._spanRef.current); return new Transform(-translateX, -translateY, 1).scale(1 / scale); }; - outerFocus = (target: Doc) => this._textBox.props.focus(this._textBox.props.Document, {}); // ideally, this would scroll to show the focus target + outerFocus = (target: Doc, options: DocFocusOptions) => this._textBox.focus(target, options); // ideally, this would scroll to show the focus target onKeyDown = (e: any) => { e.stopPropagation(); @@ -161,12 +160,12 @@ export class DashDocViewInternal extends React.Component<IDashDocViewInternal> { }; onPointerLeave = () => { - const ele = document.getElementById('DashDocCommentView-' + this.props.docid) as HTMLDivElement; + const ele = document.getElementById('DashDocCommentView-' + this.props.docId) as HTMLDivElement; ele && (ele.style.backgroundColor = ''); }; onPointerEnter = () => { - const ele = document.getElementById('DashDocCommentView-' + this.props.docid) as HTMLDivElement; + const ele = document.getElementById('DashDocCommentView-' + this.props.docId) as HTMLDivElement; ele && (ele.style.backgroundColor = 'orange'); }; @@ -212,8 +211,6 @@ export class DashDocViewInternal extends React.Component<IDashDocViewInternal> { docFilters={this.props.tbox?.props.docFilters} docRangeFilters={this.props.tbox?.props.docRangeFilters} searchFilterDocs={this.props.tbox?.props.searchFilterDocs} - ContainingCollectionView={this._textBox.props.ContainingCollectionView} - ContainingCollectionDoc={this._textBox.props.ContainingCollectionDoc} /> </div> ); diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx index b33529aeb..c43206629 100644 --- a/src/client/views/nodes/formattedText/DashFieldView.tsx +++ b/src/client/views/nodes/formattedText/DashFieldView.tsx @@ -1,5 +1,8 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Tooltip } from '@material-ui/core'; import { action, computed, IReactionDisposer, observable } from 'mobx'; import { observer } from 'mobx-react'; +import { NodeSelection } from 'prosemirror-state'; import * as ReactDOM from 'react-dom/client'; import { DataSym, Doc, DocListCast, Field } from '../../../../fields/Doc'; import { List } from '../../../../fields/List'; @@ -7,18 +10,14 @@ import { listSpec } from '../../../../fields/Schema'; import { SchemaHeaderField } from '../../../../fields/SchemaHeaderField'; import { ComputedField } from '../../../../fields/ScriptField'; import { Cast, StrCast } from '../../../../fields/Types'; +import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils'; import { DocServer } from '../../../DocServer'; +import { CollectionViewType } from '../../../documents/DocumentTypes'; +import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; +import { OpenWhere } from '../DocumentView'; import './DashFieldView.scss'; import { FormattedTextBox } from './FormattedTextBox'; import React = require('react'); -import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils'; -import { AntimodeMenu, AntimodeMenuProps } from '../../AntimodeMenu'; -import { Tooltip } from '@material-ui/core'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { CollectionViewType } from '../../../documents/DocumentTypes'; -import { NodeSelection } from 'prosemirror-state'; -import { OpenWhere } from '../DocumentView'; -import { FormattedTextBoxComment } from './FormattedTextBoxComment'; export class DashFieldView { dom: HTMLDivElement; // container for label and value @@ -55,7 +54,7 @@ export class DashFieldView { unclickable={this.unclickable} getPos={getPos} fieldKey={node.attrs.fieldKey} - docid={node.attrs.docid} + docId={node.attrs.docId} width={node.attrs.width} height={node.attrs.height} hideKey={node.attrs.hideKey} @@ -77,7 +76,7 @@ export class DashFieldView { interface IDashFieldViewInternal { fieldKey: string; - docid: string; + docId: string; hideKey: boolean; tbox: FormattedTextBox; width: number; @@ -101,8 +100,12 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna this._fieldKey = this.props.fieldKey; this._textBoxDoc = this.props.tbox.props.Document; - if (this.props.docid) { - DocServer.GetRefField(this.props.docid).then(action(async dashDoc => dashDoc instanceof Doc && (this._dashDoc = dashDoc))); + if (this.props.docId) { + DocServer.GetRefField(this.props.docId).then( + action(async dashDoc => { + dashDoc instanceof Doc && (this._dashDoc = dashDoc); + }) + ); } else { this._dashDoc = this.props.tbox.rootDoc; } @@ -113,7 +116,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna public static multiValueDelimeter = ';'; public static fieldContent(textBoxDoc: Doc, dashDoc: Doc, fieldKey: string) { - const dashVal = dashDoc[fieldKey] ?? dashDoc[DataSym][fieldKey] ?? (fieldKey === 'PARAMS' ? textBoxDoc[fieldKey] : ''); + const dashVal = dashDoc[fieldKey] ?? dashDoc[DataSym][fieldKey] ?? ''; const fval = dashVal instanceof List ? dashVal.join(DashFieldViewInternal.multiValueDelimeter) : StrCast(dashVal).startsWith(':=') || dashVal === '' ? Doc.Layout(textBoxDoc)[fieldKey] : dashVal; return { boolVal: Cast(fval, 'boolean', null), strVal: Field.toString(fval as Field) || '' }; } @@ -220,7 +223,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna Doc.SetInPlace(this._dashDoc!, this._fieldKey, Number(newText), true); } else { const splits = newText.split(DashFieldViewInternal.multiValueDelimeter); - if (this._fieldKey !== 'PARAMS' || !this._textBoxDoc[this._fieldKey] || this._dashDoc?.PARAMS) { + if (!this._textBoxDoc[this._fieldKey]) { const strVal = splits.length > 1 ? new List<string>(splits) : newText; if (this._fieldKey.startsWith('_')) Doc.Layout(this._textBoxDoc)[this._fieldKey] = strVal; Doc.SetInPlace(this._dashDoc!, this._fieldKey, strVal, true); @@ -232,10 +235,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna }; createPivotForField = (e: React.MouseEvent) => { - let container = this.props.tbox.props.ContainingCollectionView; - while (container?.props.Document.isTemplateForField || container?.props.Document.isTemplateDoc) { - container = container.props.ContainingCollectionView; - } + let container = this.props.tbox.props.DocumentView?.().props.docViewPath().lastElement(); if (container) { const alias = Doc.MakeAlias(container.props.Document); alias._viewType = CollectionViewType.Time; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 788de7af9..5719ea83c 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1,7 +1,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { isEqual } from 'lodash'; -import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from 'mobx'; +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { baseKeymap, selectAll } from 'prosemirror-commands'; import { history } from 'prosemirror-history'; @@ -11,16 +11,16 @@ import { Fragment, Mark, Node, Slice } from 'prosemirror-model'; import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from 'prosemirror-state'; import { EditorView } from 'prosemirror-view'; import { DateField } from '../../../../fields/DateField'; -import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DataSym, Doc, DocListCast, DocListCastAsync, Field, ForceServerWrite, HeightSym, Opt, UpdatingFromServer, WidthSym } from '../../../../fields/Doc'; +import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, Doc, DocListCast, Field, ForceServerWrite, HeightSym, Opt, UpdatingFromServer, WidthSym } from '../../../../fields/Doc'; import { Id } from '../../../../fields/FieldSymbols'; import { InkTool } from '../../../../fields/InkField'; import { PrefetchProxy } from '../../../../fields/Proxy'; import { RichTextField } from '../../../../fields/RichTextField'; import { RichTextUtils } from '../../../../fields/RichTextUtils'; -import { ComputedField } from '../../../../fields/ScriptField'; +import { ComputedField, ScriptField } from '../../../../fields/ScriptField'; import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils'; import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils'; import { DocServer } from '../../../DocServer'; import { Docs, DocUtils } from '../../../documents/Documents'; @@ -45,9 +45,10 @@ import { LightboxView } from '../../LightboxView'; import { AnchorMenu } from '../../pdf/AnchorMenu'; import { SidebarAnnos } from '../../SidebarAnnos'; import { StyleProp } from '../../StyleProvider'; -import { DocFocusOptions, DocumentViewInternal, OpenWhere } from '../DocumentView'; +import { DocFocusOptions, DocumentView, DocumentViewInternal, OpenWhere } from '../DocumentView'; import { FieldView, FieldViewProps } from '../FieldView'; import { LinkDocPreview } from '../LinkDocPreview'; +import { PinProps, PresBox } from '../trails'; import { DashDocCommentView } from './DashDocCommentView'; import { DashDocView } from './DashDocView'; import { DashFieldView } from './DashFieldView'; @@ -63,6 +64,7 @@ import { schema } from './schema_rts'; import { SummaryView } from './SummaryView'; import applyDevTools = require('prosemirror-dev-tools'); import React = require('react'); +import { IsFollowLinkScript } from '../../../util/LinkFollower'; const translateGoogleApi = require('translate-google-api'); export const GoogleRef = 'googleDocId'; @@ -185,7 +187,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps return ''; } public static GetDocFromUrl(url: string) { - return url.startsWith(document.location.origin) ? new URL(url).pathname.split('doc/').lastElement() : ''; // docid + return url.startsWith(document.location.origin) ? new URL(url).pathname.split('doc/').lastElement() : ''; // docId } constructor(props: any) { @@ -229,7 +231,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } } - getAnchor = (addAsAnnotation: boolean) => this.makeLinkAnchor(undefined, OpenWhere.addRight, undefined, 'Anchored Selection', false, addAsAnnotation); + getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => { + if (!pinProps && this._editorView?.state.selection.empty) return this.rootDoc; + const anchor = Docs.Create.TextanchorDocument({ annotationOn: this.rootDoc, unrendered: true }); + this.addDocument(anchor); + this.makeLinkAnchor(anchor, OpenWhere.addRight, undefined, 'Anchored Selection', false, addAsAnnotation); + PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: true } }, this.rootDoc); + return anchor; + }; @action setupAnchorMenu = () => { @@ -355,7 +364,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps let linkTime; let linkAnchor; let link; - DocListCast(this.dataDoc.links).forEach((l, i) => { + LinkManager.Links(this.dataDoc).forEach((l, i) => { const anchor = (l.anchor1 as Doc).annotationOn ? (l.anchor1 as Doc) : (l.anchor2 as Doc).annotationOn ? (l.anchor2 as Doc) : undefined; if (anchor && (anchor.annotationOn as Doc).mediaState === 'recording') { linkTime = NumCast(anchor._timecodeToShow /* audioStart */); @@ -392,7 +401,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps autoLink = () => { const newAutoLinks = new Set<Doc>(); - const oldAutoLinks = DocListCast(this.props.Document.links).filter(link => link.linkRelationship === LinkManager.AutoKeywords); + const oldAutoLinks = LinkManager.Links(this.props.Document).filter(link => link.linkRelationship === LinkManager.AutoKeywords); if (this._editorView?.state.doc.textContent) { const isNodeSel = this._editorView.state.selection instanceof NodeSelection; const f = this._editorView.state.selection.from; @@ -445,8 +454,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps if (node.firstChild === null && !node.marks.find((m: Mark) => m.type.name === schema.marks.noAutoLinkAnchor.name) && node.marks.find((m: Mark) => m.type.name === schema.marks.splitter.name)) { alink = alink ?? - (DocListCast(this.Document.links).find(link => Doc.AreProtosEqual(Cast(link.anchor1, Doc, null), this.rootDoc) && Doc.AreProtosEqual(Cast(link.anchor2, Doc, null), target)) || - DocUtils.MakeLink({ doc: this.props.Document }, { doc: target }, LinkManager.AutoKeywords)!); + (LinkManager.Links(this.Document).find(link => Doc.AreProtosEqual(Cast(link.anchor1, Doc, null), this.rootDoc) && Doc.AreProtosEqual(Cast(link.anchor2, Doc, null), target)) || + DocUtils.MakeLink(this.props.Document, target, { linkRelationship: LinkManager.AutoKeywords })!); newAutoLinks.add(alink); const allAnchors = [{ href: Doc.localServerPath(target), title: 'a link', anchorId: this.props.Document[Id] }]; allAnchors.push(...(node.marks.find((m: Mark) => m.type.name === schema.marks.autoLinkAnchor.name)?.attrs.allAnchors ?? [])); @@ -532,17 +541,18 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps // embed document when dragg marked as embed } else if (de.embedKey) { const target = dragData.droppedDocuments[0]; - target._fitContentsToBox = true; const node = schema.nodes.dashDoc.create({ width: target[WidthSym](), height: target[HeightSym](), title: 'dashDoc', - docid: target[Id], + docId: target[Id], float: 'unset', }); if (!['alias', 'copy'].includes((dragData.dropAction ?? '') as any)) { dragData.removeDocument?.(dragData.draggedDocuments[0]); } + target._fitContentsToBox = true; + target.context = this.rootDoc; const view = this._editorView!; view.dispatch(view.state.tr.insert(view.posAtCoords({ left: de.x, top: de.y })!.pos, node)); e.stopPropagation(); @@ -679,7 +689,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps @undoBatch deleteAnnotation = (anchor: Doc) => { - LinkManager.Instance.deleteLink(DocListCast(anchor.links)[0]); + LinkManager.Instance.deleteLink(LinkManager.Links(anchor)[0]); // const docAnnotations = DocListCast(this.props.dataDoc[this.fieldKey]); // this.props.dataDoc[this.fieldKey] = new List<Doc>(docAnnotations.filter(a => a !== this.annoTextRegion)); // AnchorMenu.Instance.fadeOut(true); @@ -782,12 +792,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps runInAction(() => (this.layoutDoc._highlights = FormattedTextBox._globalHighlights.join(''))); this.updateHighlights(); }, - icon: 'expand-arrows-alt', + icon: FormattedTextBox._globalHighlights.indexOf(option) === -1 ? 'highlighter' : 'remove-format', }) ); const uicontrols: ContextMenuProps[] = []; - uicontrols.push({ description: !this.Document._noSidebar ? 'Hide Sidebar Handle' : 'Show Sidebar Handle', event: () => (this.layoutDoc._noSidebar = !this.layoutDoc._noSidebar), icon: 'expand-arrows-alt' }); + uicontrols.push({ description: !this.Document._noSidebar ? 'Hide Sidebar Handle' : 'Show Sidebar Handle', event: () => (this.layoutDoc._noSidebar = !this.layoutDoc._noSidebar), icon: !this.Document._noSidebar ? 'eye-slash' : 'eye' }); uicontrols.push({ description: 'Show Highlights...', noexpand: true, subitems: highlighting, icon: 'hand-point-right' }); !Doc.noviceMode && uicontrols.push({ @@ -836,8 +846,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps const options = cm.findByDescription('Options...'); const optionItems = options && 'subitems' in options ? options.subitems : []; - optionItems.push({ description: !this.Document._singleLine ? 'Make Single Line' : 'Make Multi Line', event: () => (this.layoutDoc._singleLine = !this.layoutDoc._singleLine), icon: 'expand-arrows-alt' }); - optionItems.push({ description: `${this.Document._autoHeight ? 'Lock' : 'Auto'} Height`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: 'plus' }); + optionItems.push({ description: !this.Document._singleLine ? 'Make Single Line' : 'Make Multi Line', event: () => (this.layoutDoc._singleLine = !this.layoutDoc._singleLine), icon: !this.Document._singleLine ? 'grip-lines' : 'bars' }); + optionItems.push({ description: `${this.Document._autoHeight ? 'Lock' : 'Auto'} Height`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: this.Document._autoHeight ? 'lock' : 'unlock' }); !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' }); this._downX = this._downY = Number.NaN; }; @@ -871,7 +881,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps if (this._editorView && this._recordingStart) { if (this._break) { const textanchorFunc = () => { - const tanch = Docs.Create.TextanchorDocument({ title: 'dictation anchor' }); + const tanch = Docs.Create.TextanchorDocument({ title: 'dictation anchor', unrendered: true }); return this.addDocument(tanch) ? tanch : undefined; }; const link = DocUtils.MakeLinkToActiveAudio(textanchorFunc, false).lastElement(); @@ -932,19 +942,22 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps return anchorDoc ?? this.rootDoc; } - scrollFocus = (textAnchor: Doc, options: DocFocusOptions) => { - let didToggle = false; - if (DocListCast(this.Document[this.fieldKey + '-sidebar']).includes(textAnchor) && !this.SidebarShown) { - this.toggleSidebar(options.preview); - didToggle = true; + getView = async (doc: Doc) => { + if (DocListCast(this.rootDoc[this.SidebarKey]).find(anno => Doc.AreProtosEqual(doc.unrendered ? DocCast(doc.annotationOn) : doc, anno))) { + !this.SidebarShown && this.toggleSidebar(false); + setTimeout(() => this._sidebarRef?.current?.makeDocUnfiltered(doc)); } + return new Promise<Opt<DocumentView>>(res => DocumentManager.Instance.AddViewRenderedCb(doc, dv => res(dv))); + }; + focus = (textAnchor: Doc, options: DocFocusOptions) => { + const focusSpeed = options.zoomTime ?? 500; const textAnchorId = textAnchor[Id]; const findAnchorFrag = (frag: Fragment, editor: EditorView) => { const nodes: Node[] = []; let hadStart = start !== 0; frag.forEach((node, index) => { const examinedNode = findAnchorNode(node, editor); - if (examinedNode?.node && (examinedNode.node.textContent || examinedNode.node.type === this._editorView?.state.schema.nodes.audiotag)) { + if (examinedNode?.node && (examinedNode.node.textContent || examinedNode.node.type === this._editorView?.state.schema.nodes.dashDoc || examinedNode.node.type === this._editorView?.state.schema.nodes.audiotag)) { nodes.push(examinedNode.node); !hadStart && (start = index + examinedNode.start); hadStart = true; @@ -959,9 +972,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } return undefined; } + if (node.type === this._editorView?.state.schema.nodes.dashDoc) { + if (node.attrs.docId === textAnchorId) { + return { node, start: 0 }; + } + return undefined; + } if (!node.isText) { const content = findAnchorFrag(node.content, editor); - return { node: node.copy(content.frag), start: content.start }; + if (content.frag.childCount) return { node: content.frag.childCount ? content.frag.child(0) : node, start: content.start }; } const marks = [...node.marks]; const linkIndex = marks.findIndex(mark => mark.type === editor.state.schema.marks.linkAnchor); @@ -975,8 +994,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps const ret = findAnchorFrag(editor.state.doc.content, editor); const content = (ret.frag as any)?.content; - if ((ret.frag.size > 2 || (content?.length && content[0].type === this._editorView.state.schema.nodes.audiotag)) && ret.start >= 0) { - !options.instant && (this._focusSpeed = 500); + if ((ret.frag.size || (content?.length && content[0].type === this._editorView.state.schema.nodes.dashDoc) || (content?.length && content[0].type === this._editorView.state.schema.nodes.audiotag)) && ret.start >= 0) { + !options.instant && (this._focusSpeed = focusSpeed); let selection = TextSelection.near(editor.state.doc.resolve(ret.start)); // default to near the start if (ret.frag.firstChild) { selection = TextSelection.between(editor.state.doc.resolve(ret.start), editor.state.doc.resolve(ret.start + ret.frag.firstChild.nodeSize)); // bcz: looks better to not have the target selected @@ -986,10 +1005,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps addStyleSheetRule(FormattedTextBox._highlightStyleSheet, `${escAnchorId}`, { background: 'yellow', transform: 'scale(3)', 'transform-origin': 'left bottom' }); setTimeout(() => (this._focusSpeed = undefined), this._focusSpeed); setTimeout(() => clearStyleSheetRules(FormattedTextBox._highlightStyleSheet), Math.max(this._focusSpeed || 0, 3000)); + return focusSpeed; + } else { + return this.props.focus(this.rootDoc, options); } } - - return this._didScroll ? this._focusSpeed : didToggle ? 1 : undefined; // if we actually scrolled, then return some focusSpeed }; // if the scroll height has changed and we're in autoHeight mode, then we need to update the textHeight component of the doc. @@ -1005,7 +1025,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } componentDidMount() { !this.props.dontSelectOnLoad && this.props.setContentView?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link. - this._cachedLinks = DocListCast(this.Document.links); + this._cachedLinks = LinkManager.Links(this.Document); this._disposers.breakupDictation = reaction(() => DocumentManager.Instance.RecordingEvent, this.breakupDictation); this._disposers.autoHeight = reaction( () => this.autoHeight, @@ -1032,7 +1052,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps { fireImmediately: true } ); this._disposers.links = reaction( - () => DocListCast(this.dataDoc.links), // if a link is deleted, then remove all hyperlinks that reference it from the text's marks + () => LinkManager.Links(this.dataDoc), // if a link is deleted, then remove all hyperlinks that reference it from the text's marks newLinks => { this._cachedLinks.forEach(l => !newLinks.includes(l) && this.RemoveLinkFromDoc(l)); this._cachedLinks = newLinks; @@ -1251,7 +1271,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps DocServer.GetRefField(pdfAnchorId).then(pdfAnchor => { if (pdfAnchor instanceof Doc) { const dashField = view.state.schema.nodes.paragraph.create({}, [ - view.state.schema.nodes.dashField.create({ fieldKey: 'text', docid: pdfAnchor[Id], hideKey: true, editable: false }, undefined, [ + view.state.schema.nodes.dashField.create({ fieldKey: 'text', docId: pdfAnchor[Id], hideKey: true, editable: false }, undefined, [ view.state.schema.marks.linkAnchor.create({ allAnchors: [{ href: `/doc/${this.rootDoc[Id]}`, title: this.rootDoc.title, anchorId: `${this.rootDoc[Id]}` }], location: 'add:right', @@ -1264,7 +1284,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps ]), ]); - const link = DocUtils.MakeLink({ doc: pdfAnchor }, { doc: this.rootDoc }, 'PDF pasted'); + const link = DocUtils.MakeLink(pdfAnchor, this.rootDoc, { linkRelationship: 'PDF pasted' }); if (link) { view.dispatch(view.state.tr.replaceSelectionWith(dashField, false).scrollIntoView().setMeta('paste', true).setMeta('uiEvent', 'paste')); } @@ -1426,7 +1446,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } else (e.nativeEvent as any).handledByInnerReactInstance = true; if (this.Document.forceActive) e.stopPropagation(); - this.tryUpdateScrollHeight(); // if a doc a fitwidth doc is being viewed in different context (eg freeform & lightbox), then it will have conflicting heights. so when the doc is clicked on, we want to make sure it has the appropriate height for the selected view. + this.tryUpdateScrollHeight(); // if a doc a fitWidth doc is being viewed in different context (eg freeform & lightbox), then it will have conflicting heights. so when the doc is clicked on, we want to make sure it has the appropriate height for the selected view. if ((e.target as any).tagName === 'AUDIOTAG') { e.preventDefault(); e.stopPropagation(); @@ -1461,22 +1481,19 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps // but that's changed, so this shouldn't be needed. //e.stopPropagation(); // if the text box is selected, then it consumes all down events document.addEventListener('pointerup', this.onSelectEnd); - document.addEventListener('pointermove', this.onSelectMove); } } if (e.button === 2 || (e.button === 0 && e.ctrlKey)) { e.preventDefault(); } }; - onSelectMove = (e: PointerEvent) => e.stopPropagation(); onSelectEnd = (e: PointerEvent) => { document.removeEventListener('pointerup', this.onSelectEnd); - document.removeEventListener('pointermove', this.onSelectMove); }; onPointerUp = (e: React.PointerEvent): void => { const editor = this._editorView!; const state = editor?.state; - if (!state || !editor) return; + if (!state || !editor || !this.ProseRef?.children[0].className.includes('-focused')) return; if (!state.selection.empty && !(state.selection instanceof NodeSelection)) this.setupAnchorMenu(); else if (this.props.isContentActive(true)) { const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY }); @@ -1488,10 +1505,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps return; } } - - if (e.button === 0 && this.props.isSelected(true) && !e.altKey) { - e.stopPropagation(); - } }; @action onDoubleClick = (e: React.MouseEvent): void => { @@ -1526,6 +1539,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps @observable public static Focused: FormattedTextBox | undefined; onClick = (e: React.MouseEvent): void => { + if (!this.props.isContentActive()) return; if ((e.nativeEvent as any).handledByInnerReactInstance) { e.stopPropagation(); return; @@ -1557,8 +1571,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps if (this.props.isSelected(true)) { // if text box is selected, then it consumes all click events (e.nativeEvent as any).handledByInnerReactInstance = true; - if (this.ProseRef?.children[0] !== e.nativeEvent.target) e.stopPropagation(); // if you double click on text, then it will be selected instead of sending a double click to DocumentView & opening a lightbox. Also,if a text box has isLinkButton, this will prevent link following if you've selected the document to edit it. - // e.stopPropagation(); // bcz: not sure why this was here. We need to allow the DocumentView to get clicks to process doubleClicks (see above comment) this.hitBulletTargets(e.clientX, e.clientY, !this._editorView?.state.selection.empty || this._forceUncollapse, false, this._forceDownNode, e.shiftKey); } this._forceUncollapse = !(this._editorView!.root as any).getSelection().isCollapsed; @@ -1660,8 +1672,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps }; onKeyDown = (e: React.KeyboardEvent) => { - if (e.altKey) { + if ((e.altKey || e.ctrlKey) && e.key === 't') { e.preventDefault(); + e.stopPropagation(); + this.props.setTitleFocus?.(); return; } const state = this._editorView!.state; @@ -1712,6 +1726,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps this._ignoreScroll = true; this.layoutDoc._scrollTop = this._scrollRef.current.scrollTop; this._ignoreScroll = false; + e.stopPropagation(); + e.preventDefault(); } } }; @@ -1734,12 +1750,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } } }; - fitContentsToBox = () => this.props.Document._fitContentsToBox; + fitContentsToBox = () => BoolCast(this.props.Document._fitContentsToBox); sidebarContentScaling = () => (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1); sidebarAddDocument = (doc: Doc | Doc[], sidebarKey: string = this.SidebarKey) => { if (!this.layoutDoc._showSidebar) this.toggleSidebar(); - // console.log("printting allSideBarDocs"); - // console.log(this.allSidebarDocs); return this.addDocument(doc, sidebarKey); }; sidebarMoveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.moveDocument(doc, targetCollection, addDocument, this.SidebarKey); @@ -1780,8 +1794,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown} style={{ - backgroundColor: backgroundColor, - color: color, + backgroundColor, + color, opacity: annotated ? 1 : undefined, }}> <FontAwesomeIcon icon={'comment-alt'} /> @@ -1795,39 +1809,41 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps <SidebarAnnos ref={this._sidebarRef} {...this.props} - fieldKey={this.fieldKey} rootDoc={this.rootDoc} layoutDoc={this.layoutDoc} dataDoc={this.dataDoc} - ScreenToLocalTransform={this.sidebarScreenToLocal} + usePanelWidth={true} nativeWidth={NumCast(this.layoutDoc._nativeWidth)} - whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} showSidebar={this.SidebarShown} - PanelWidth={this.sidebarWidth} - setHeight={this.setSidebarHeight} + whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} sidebarAddDocument={this.sidebarAddDocument} moveDocument={this.moveDocument} removeDocument={this.removeDocument} + ScreenToLocalTransform={this.sidebarScreenToLocal} + fieldKey={this.fieldKey} + PanelWidth={this.sidebarWidth} + setHeight={this.setSidebarHeight} /> ) : ( <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.props.DocumentView?.()!, false), true)}> <ComponentTag - {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit} + {...this.props} + setContentView={emptyFunction} NativeWidth={returnZero} NativeHeight={returnZero} PanelHeight={this.props.PanelHeight} PanelWidth={this.sidebarWidth} xPadding={0} yPadding={0} - scaleField={this.SidebarKey + '-scale'} + viewField={this.SidebarKey} isAnnotationOverlay={false} select={emptyFunction} + isAnyChildContentActive={returnFalse} NativeDimScaling={this.sidebarContentScaling} whenChildContentsActiveChanged={this.whenChildContentsActiveChanged} removeDocument={this.sidebarRemDocument} moveDocument={this.sidebarMoveDocument} addDocument={this.sidebarAddDocument} - CollectionView={undefined} ScreenToLocalTransform={this.sidebarScreenToLocal} renderDepth={this.props.renderDepth + 1} setHeight={this.setSidebarHeight} @@ -1862,7 +1878,18 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps return styleFromLayoutString?.height === '0px' ? null : ( <div className="formattedTextBox-cont" - onWheel={e => this.props.isContentActive() && e.stopPropagation()} + ref={r => + r?.addEventListener( + 'wheel', // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this) + (e: WheelEvent) => { + if (this.props.isContentActive()) { + if (!NumCast(this.layoutDoc._scrollTop) && e.deltaY <= 0) e.preventDefault(); + e.stopPropagation(); + } + }, + { passive: false } + ) + } style={{ ...(this.props.dontScale ? {} @@ -1916,7 +1943,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps paddingRight: StrCast(this.layoutDoc._textBoxPaddingX, `${paddingX - selPad}px`), paddingTop: StrCast(this.layoutDoc._textBoxPaddingY, `${paddingY - selPad}px`), paddingBottom: StrCast(this.layoutDoc._textBoxPaddingY, `${paddingY - selPad}px`), - pointerEvents: !active && !SnappingManager.GetIsDragging() ? (this.layoutDoc.isLinkButton ? 'none' : undefined) : undefined, + pointerEvents: !active && !SnappingManager.GetIsDragging() ? (IsFollowLinkScript(this.layoutDoc.onClick) ? 'none' : undefined) : undefined, }} /> </div> diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index 5675776fb..e691869cc 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -89,8 +89,8 @@ export class RichTextRules { textDoc[inlineLayoutKey] = FormattedTextBox.LayoutString(inlineFieldKey); // create a layout string for the layout key that will render the annotation text textDoc[inlineFieldKey] = ''; // set a default value for the annotation const node = (state.doc.resolve(start) as any).nodeAfter; - const newNode = schema.nodes.dashComment.create({ docid: textDocInline[Id] }); - const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: 'dashDoc', docid: textDocInline[Id], float: 'right' }); + const newNode = schema.nodes.dashComment.create({ docId: textDocInline[Id] }); + const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: 'dashDoc', docId: textDocInline[Id], float: 'right' }); const sm = state.storedMarks || undefined; const replaced = node ? state.tr @@ -248,18 +248,18 @@ export class RichTextRules { // [[fieldKey:Doc]] => show field of doc new InputRule(new RegExp(/\[\[([a-zA-Z_\? \-0-9]*)(=[a-zA-Z_@\? /\-0-9]*)?(:[a-zA-Z_@:\.\? \-0-9]+)?\]\]$/), (state, match, start, end) => { const fieldKey = match[1]; - const docid = match[3]?.replace(':', ''); + const docId = match[3]?.replace(':', ''); const value = match[2]?.substring(1); if (!fieldKey) { - if (docid) { - DocServer.GetRefField(docid).then(docx => { + if (docId) { + DocServer.GetRefField(docId).then(docx => { const rstate = this.TextBox.EditorView?.state; const selection = rstate?.selection.$from.pos; if (rstate) { this.TextBox.EditorView?.dispatch(rstate.tr.setSelection(new TextSelection(rstate.doc.resolve(start), rstate.doc.resolve(end - 3)))); } - const target = (docx instanceof Doc && docx) || Docs.Create.FreeformDocument([], { title: docid, _width: 500, _height: 500 }, docid); - DocUtils.MakeLink({ doc: this.TextBox.getAnchor(true) }, { doc: target }, 'portal to:portal from', undefined); + const target = (docx instanceof Doc && docx) || Docs.Create.FreeformDocument([], { title: docId, _width: 500, _height: 500 }, docId); + DocUtils.MakeLink(this.TextBox.getAnchor(true), target, { linkRelationship: 'portal to:portal from' }); const fstate = this.TextBox.EditorView?.state; if (fstate && selection) { @@ -274,7 +274,7 @@ export class RichTextRules { const num = value.match(/^[0-9.]$/); this.Document[DataSym][fieldKey] = value === 'true' ? true : value === 'false' ? false : num ? Number(value) : value; } - const fieldView = state.schema.nodes.dashField.create({ fieldKey, docid, hideKey: false }); + const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId, hideKey: false }); return state.tr.setSelection(new TextSelection(state.doc.resolve(start), state.doc.resolve(end))).replaceSelectionWith(fieldView, true); }), @@ -311,16 +311,16 @@ export class RichTextRules { const fieldKey = match[1] || ''; const fieldParam = match[2]?.replace('…', '...') || ''; const rawdocid = match[3]?.substring(1); - const docid = rawdocid ? (!rawdocid.includes('@') ? normalizeEmail(Doc.CurrentUserEmail) + '@' + rawdocid : rawdocid) : undefined; - if (!fieldKey && !docid) return state.tr; - docid && - DocServer.GetRefField(docid).then(docx => { + const docId = rawdocid ? (!rawdocid.includes('@') ? normalizeEmail(Doc.CurrentUserEmail) + '@' + rawdocid : rawdocid) : undefined; + if (!fieldKey && !docId) return state.tr; + docId && + DocServer.GetRefField(docId).then(docx => { if (!(docx instanceof Doc && docx)) { - Docs.Create.FreeformDocument([], { title: rawdocid, _width: 500, _height: 500 }, docid); + Docs.Create.FreeformDocument([], { title: rawdocid, _width: 500, _height: 500 }, docId); } }); const node = (state.doc.resolve(start) as any).nodeAfter; - const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 75, title: 'dashDoc', docid, fieldKey: fieldKey + fieldParam, float: 'unset', alias: Utils.GenerateGuid() }); + const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 75, title: 'dashDoc', docId, fieldKey: fieldKey + fieldParam, float: 'unset', alias: Utils.GenerateGuid() }); const sm = state.storedMarks || undefined; return node ? state.tr.replaceRangeWith(start, end, dashDoc).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; }), diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts index aa2475dca..6c9d5d31a 100644 --- a/src/client/views/nodes/formattedText/nodes_rts.ts +++ b/src/client/views/nodes/formattedText/nodes_rts.ts @@ -176,7 +176,7 @@ export const nodes: { [index: string]: NodeSpec } = { dashComment: { attrs: { - docid: { default: '' }, + docId: { default: '' }, }, inline: true, group: 'inline', @@ -213,7 +213,7 @@ export const nodes: { [index: string]: NodeSpec } = { title: { default: null }, float: { default: 'left' }, location: { default: 'add:right' }, - docid: { default: '' }, + docId: { default: '' }, }, group: 'inline', draggable: true, @@ -246,7 +246,7 @@ export const nodes: { [index: string]: NodeSpec } = { float: { default: 'right' }, hidden: { default: false }, // whether dashComment node has toggle the dashDoc's display off fieldKey: { default: '' }, - docid: { default: '' }, + docId: { default: '' }, alias: { default: '' }, }, group: 'inline', @@ -261,7 +261,7 @@ export const nodes: { [index: string]: NodeSpec } = { inline: true, attrs: { fieldKey: { default: '' }, - docid: { default: '' }, + docId: { default: '' }, hideKey: { default: false }, editable: { default: true }, }, |