aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/formattedText
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-03-28 23:28:11 -0400
committerbobzel <zzzman@gmail.com>2024-03-28 23:28:11 -0400
commit82a74549a6b1c942fabaf8396c450b70d65e81dd (patch)
tree3b32fd250d34422107b02a1c5352302b4048fd29 /src/client/views/nodes/formattedText
parent75a520e2cbdd611fcd1846540c42c25df9f70241 (diff)
fixed following link to pdf text selection with highlights. fixed hide key/value in dashfieldView. fixed selecting dashFieldView nodes.
Diffstat (limited to 'src/client/views/nodes/formattedText')
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx70
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx32
-rw-r--r--src/client/views/nodes/formattedText/RichTextRules.ts3
-rw-r--r--src/client/views/nodes/formattedText/nodes_rts.ts1
4 files changed, 76 insertions, 30 deletions
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index 8802a032f..cdfeebe66 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -22,7 +22,7 @@ import { OpenWhere } from '../DocumentView';
import './DashFieldView.scss';
import { FormattedTextBox } from './FormattedTextBox';
import { DocData } from '../../../../fields/DocSymbols';
-import { NodeSelection, TextSelection } from 'prosemirror-state';
+import { NodeSelection } from 'prosemirror-state';
export class DashFieldView {
dom: HTMLDivElement; // container for label and value
@@ -60,7 +60,7 @@ export class DashFieldView {
return;
}
}
- tBox.setFocus(state.selection.to + 1);
+ tBox.setFocus(state.selection.to);
}
}
};
@@ -84,6 +84,7 @@ export class DashFieldView {
width={node.attrs.width}
height={node.attrs.height}
hideKey={node.attrs.hideKey}
+ hideValue={node.attrs.hideValue}
editable={node.attrs.editable}
expanded={this.Expanded}
dataDoc={node.attrs.dataDoc}
@@ -112,6 +113,7 @@ interface IDashFieldViewInternal {
fieldKey: string;
docId: string;
hideKey: boolean;
+ hideValue: boolean;
tbox: FormattedTextBox;
width: number;
height: number;
@@ -217,12 +219,28 @@ export class DashFieldViewInternal extends ObservableReactComponent<IDashFieldVi
};
toggleFieldHide = undoable(
- action(() => this._dashDoc && (this._dashDoc[this._fieldKey + '_hideKey'] = !this._dashDoc[this._fieldKey + '_hideKey'])),
+ action(() => {
+ const editor = this._props.tbox.EditorView!;
+ editor.dispatch(editor.state.tr.setNodeMarkup(this._props.getPos(), this._props.node.type, { ...this._props.node.attrs, hideKey: !this._props.node.attrs.hideKey ? true : false }));
+ }),
'hideKey'
);
+ toggleValueHide = undoable(
+ action(() => {
+ const editor = this._props.tbox.EditorView!;
+ editor.dispatch(editor.state.tr.setNodeMarkup(this._props.getPos(), this._props.node.type, { ...this._props.node.attrs, hideValue: !this._props.node.attrs.hideValue ? true : false }));
+ }),
+ 'hideValue'
+ );
+
+ @observable _showValue = false;
@computed get _hideKey() {
- return this._dashDoc?.[this._fieldKey + '_hideKey'] && !this._expanded;
+ return this._props.hideKey && !this._expanded;
+ }
+
+ @computed get _hideValue() {
+ return !this._showValue && this._props.hideValue && !this._expanded;
}
// clicking on the label creates a pivot view collection of all documents
@@ -231,7 +249,11 @@ export class DashFieldViewInternal extends ObservableReactComponent<IDashFieldVi
setupMoveUpEvents(this, e, returnFalse, returnFalse, e => {
DashFieldViewMenu.createFieldView = this.createPivotForField;
DashFieldViewMenu.toggleFieldHide = this.toggleFieldHide;
+ DashFieldViewMenu.toggleValueHide = this.toggleValueHide;
DashFieldViewMenu.Instance.show(e.clientX, e.clientY + 16, this._fieldKey);
+ this._dashDoc?.[this._fieldKey + '_hideValue'] && runInAction(() => (this._showValue = !this._showValue));
+ const editor = this._props.tbox.EditorView!;
+ setTimeout(() => editor.dispatch(editor.state.tr.setSelection(new NodeSelection(editor.state.doc.resolve(this._props.getPos())))), 100);
});
};
@@ -257,12 +279,12 @@ export class DashFieldViewInternal extends ObservableReactComponent<IDashFieldVi
height: this._props.height,
pointerEvents: this._props.tbox._props.rootSelected?.() || this._props.tbox.isAnyChildContentActive?.() ? undefined : 'none',
}}>
- {this._props.hideKey || this._hideKey ? null : (
+ {this._hideKey ? null : (
<span className="dashFieldView-labelSpan" title="click to see related tags" onPointerDown={this.onPointerDownLabelSpan}>
{(Doc.AreProtosEqual(DocCast(this._textBoxDoc.rootDocument) ?? this._textBoxDoc, DocCast(this._dashDoc?.rootDocument) ?? this._dashDoc) ? '' : this._dashDoc?.title + ':') + this._fieldKey}
</span>
)}
- {this._props.fieldKey.startsWith('#') ? null : this.fieldValueContent}
+ {this._props.fieldKey.startsWith('#') || this._hideValue ? null : this.fieldValueContent}
{/* {!this.values.length ? null : (
<select className="dashFieldView-select" tabIndex={-1} onChange={this.selectVal}>
{this.values.map(val => (
@@ -279,6 +301,7 @@ export class DashFieldViewMenu extends AntimodeMenu<AntimodeMenuProps> {
static Instance: DashFieldViewMenu;
static createFieldView: (e: React.MouseEvent) => void = emptyFunction;
static toggleFieldHide: () => void = emptyFunction;
+ static toggleValueHide: () => void = emptyFunction;
constructor(props: any) {
super(props);
DashFieldViewMenu.Instance = this;
@@ -292,6 +315,10 @@ export class DashFieldViewMenu extends AntimodeMenu<AntimodeMenuProps> {
DashFieldViewMenu.toggleFieldHide();
DashFieldViewMenu.Instance.fadeOut(true);
};
+ toggleValueHide = (e: React.MouseEvent) => {
+ DashFieldViewMenu.toggleValueHide();
+ DashFieldViewMenu.Instance.fadeOut(true);
+ };
@observable _fieldKey = '';
@@ -308,16 +335,27 @@ export class DashFieldViewMenu extends AntimodeMenu<AntimodeMenuProps> {
render() {
return this.getElement(
<>
- <Tooltip key="trash" title={<div className="dash-tooltip">{`Show Pivot Viewer for '${this._fieldKey}'`}</div>}>
- <button className="antimodeMenu-button" onPointerDown={this.showFields}>
- <FontAwesomeIcon icon="eye" size="lg" />
- </button>
- </Tooltip>
- <Tooltip key="trash" title={<div className="dash-tooltip">Toggle view of field key</div>}>
- <button className="antimodeMenu-button" onPointerDown={this.toggleFieldHide}>
- <FontAwesomeIcon icon="bullseye" size="lg" />
- </button>
- </Tooltip>
+ {!this._fieldKey.startsWith('#') ? null : (
+ <Tooltip key="trash" title={<div className="dash-tooltip">{`Show Pivot Viewer for '${this._fieldKey}'`}</div>}>
+ <button className="antimodeMenu-button" onPointerDown={this.showFields}>
+ <FontAwesomeIcon icon="eye" size="sm" />
+ </button>
+ </Tooltip>
+ )}
+ {this._fieldKey.startsWith('#') ? null : (
+ <Tooltip key="key" title={<div className="dash-tooltip">Toggle view of field key</div>}>
+ <button className="antimodeMenu-button" onPointerDown={this.toggleFieldHide}>
+ <FontAwesomeIcon icon="bullseye" size="sm" />
+ </button>
+ </Tooltip>
+ )}
+ {this._fieldKey.startsWith('#') ? null : (
+ <Tooltip key="val" title={<div className="dash-tooltip">Toggle view of field value</div>}>
+ <button className="antimodeMenu-button" onPointerDown={this.toggleValueHide}>
+ <FontAwesomeIcon icon="hashtag" size="sm" />
+ </button>
+ </Tooltip>
+ )}
</>
);
}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index f06e5fad0..39d4893ab 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -104,7 +104,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
private _dropDisposer?: DragManager.DragDropDisposer;
private _recordingStart: number = 0;
private _ignoreScroll = false;
- private _hadDownFocus = false;
private _focusSpeed: Opt<number>;
private _keymap: any = undefined;
private _rules: RichTextRules | undefined;
@@ -328,7 +327,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
if (node.type === this._editorView?.state.schema.nodes.dashField) {
const refDoc = !node.attrs.docId ? this.Document : (DocServer.GetCachedRefField(node.attrs.docId as string) as Doc);
const fieldKey = StrCast(node.attrs.fieldKey);
- return fieldKey + ':' + Field.toJavascriptString(refDoc[fieldKey] as Field);
+ return (
+ (node.attrs.hideKey ? '' : '"' + fieldKey + '"' + ':') + //
+ (node.attrs.hideValue ? '' : Field.toJavascriptString(refDoc[fieldKey] as Field))
+ );
}
return '';
};
@@ -383,7 +385,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
} else {
// if we've deleted all the text in a note driven by a template, then restore the template data
dataDoc[this.fieldKey] = undefined;
- this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse((layoutData ?? protoData ?? prevData).Data)));
+ this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse(((layoutData !== prevData ? layoutData : undefined) ?? protoData).Data)));
ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, text: newText });
unchanged = false;
}
@@ -1363,7 +1365,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
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, expanded: true }, undefined, [
+ view.state.schema.nodes.dashField.create({ fieldKey: 'text', docId: pdfAnchor[Id], hideKey: true, hideValue: false, editable: false, expanded: true }, undefined, [
view.state.schema.marks.linkAnchor.create({
allAnchors: [{ href: `/doc/${this.Document[Id]}`, title: this.Document.title, anchorId: `${this.Document[Id]}` }],
title: StrCast(pdfAnchor.title),
@@ -1577,7 +1579,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
(this.ProseRef?.children?.[0] as any).focus();
}
}
- this._hadDownFocus = this.ProseRef?.children[0].className.includes('focused') ?? false;
if (e.button === 2 || (e.button === 0 && e.ctrlKey)) {
e.preventDefault();
}
@@ -1588,9 +1589,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
onPointerUp = (e: React.PointerEvent): void => {
const editor = this._editorView!;
const state = editor?.state;
- if (!Utils.isClick(e.clientX, e.clientY, this._downX, this._downY, this._downTime) && !this._hadDownFocus) {
- (this.ProseRef?.children[0] as HTMLElement)?.blur?.();
- }
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() && !e.button) {
@@ -1599,10 +1597,18 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
while (xpos > 0 && !state.doc.resolve(xpos).node()?.isTextblock) {
xpos = xpos - 1;
}
- editor.dispatch(state.tr.setSelection(new TextSelection(state.doc.resolve(xpos))));
- let target = e.target as any; // hrefs are stored on the dataset of the <a> node that wraps the hyerlink <span>
- while (target && !target.dataset?.targethrefs) target = target.parentElement;
- FormattedTextBoxComment.update(this, editor, undefined, target?.dataset?.targethrefs, target?.dataset.linkdoc, target?.dataset.nopreview === 'true');
+ let node: any;
+ try {
+ node = state.doc.nodeAt(xpos);
+ } catch (e) {}
+ if (node?.type !== schema.nodes.dashFieldView) {
+ editor.dispatch(state.tr.setSelection(new TextSelection(state.doc.resolve(xpos))));
+ let target = e.target as any; // hrefs are stored on the dataset of the <a> node that wraps the hyerlink <span>
+ while (target && !target.dataset?.targethrefs) target = target.parentElement;
+ FormattedTextBoxComment.update(this, editor, undefined, target?.dataset?.targethrefs, target?.dataset.linkdoc, target?.dataset.nopreview === 'true');
+ } else {
+ editor.dispatch(state.tr.setSelection(new NodeSelection(state.doc.resolve(xpos))));
+ }
}
};
@action
@@ -1800,7 +1806,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
default:
if (this._lastTimedMark?.attrs.userid === Doc.CurrentUserEmail) break;
case ' ':
- if (e.code !== 'Space') {
+ if (e.code !== 'Space' && e.code !== 'Backspace') {
[AclEdit, AclAugment, AclAdmin].includes(GetEffectiveAcl(this.Document)) &&
this._editorView!.dispatch(this._editorView!.state.tr.removeStoredMark(schema.marks.user_mark).addStoredMark(schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })));
}
diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts
index 7afe91e94..418ec92ef 100644
--- a/src/client/views/nodes/formattedText/RichTextRules.ts
+++ b/src/client/views/nodes/formattedText/RichTextRules.ts
@@ -137,6 +137,7 @@ export class RichTextRules {
textDocInline.title = inlineFieldKey; // give the annotation its own title
textDocInline.title_custom = true; // And make sure that it's 'custom' so that editing text doesn't change the title of the containing doc
textDocInline.isTemplateForField = inlineFieldKey; // this is needed in case the containing text doc is converted to a template at some point
+ textDocInline.isDataDoc = true;
textDocInline.proto = textDoc; // make the annotation inherit from the outer text doc so that it can resolve any nested field references, e.g., [[field]]
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
@@ -349,7 +350,7 @@ export class RichTextRules {
if (fieldKey === this.TextBox.fieldKey) return this.TextBox.EditorView!.state.tr;
}
const target = docTitle ? getTitledDoc(docTitle) : undefined;
- const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId: target?.[Id], hideKey: false, dataDoc });
+ const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId: target?.[Id], hideKey: false, hideValue: false, dataDoc });
return state.tr.setSelection(new TextSelection(state.doc.resolve(start), state.doc.resolve(end))).replaceSelectionWith(fieldView, true);
},
{ inCode: true }
diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts
index 905146ee2..6862eecef 100644
--- a/src/client/views/nodes/formattedText/nodes_rts.ts
+++ b/src/client/views/nodes/formattedText/nodes_rts.ts
@@ -264,6 +264,7 @@ export const nodes: { [index: string]: NodeSpec } = {
fieldKey: { default: '' },
docId: { default: '' },
hideKey: { default: false },
+ hideValue: { default: false },
editable: { default: true },
expanded: { default: null },
dataDoc: { default: false },