aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/formattedText/DashFieldView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/formattedText/DashFieldView.tsx')
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx94
1 files changed, 67 insertions, 27 deletions
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index d2f7b5677..21ccf3bc7 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -1,35 +1,39 @@
+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 * as ReactDOM from 'react-dom';
+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';
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';
export class DashFieldView {
dom: HTMLDivElement; // container for label and value
+ root: any;
+ node: any;
+ tbox: FormattedTextBox;
+ unclickable = () => !this.tbox.props.isSelected() && this.node.marks.some((m: any) => m.type === this.tbox.EditorView?.state.schema.marks.linkAnchor && m.attrs.noPreview);
constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) {
- const { boolVal, strVal } = DashFieldViewInternal.fieldContent(tbox.props.Document, tbox.rootDoc, node.attrs.fieldKey);
-
+ this.node = node;
+ this.tbox = tbox;
this.dom = document.createElement('div');
this.dom.style.width = node.attrs.width;
this.dom.style.height = node.attrs.height;
- this.dom.style.fontWeight = 'bold';
this.dom.style.position = 'relative';
this.dom.style.display = 'inline-block';
- this.dom.textContent = node.attrs.fieldKey.startsWith('#') ? node.attrs.fieldKey : node.attrs.fieldKey + ' ' + strVal;
this.dom.onkeypress = function (e: any) {
e.stopPropagation();
};
@@ -43,22 +47,44 @@ export class DashFieldView {
e.stopPropagation();
};
- setTimeout(() => ReactDOM.render(<DashFieldViewInternal fieldKey={node.attrs.fieldKey} docid={node.attrs.docid} width={node.attrs.width} height={node.attrs.height} hideKey={node.attrs.hideKey} tbox={tbox} />, this.dom));
- (this as any).dom = this.dom;
+ this.root = ReactDOM.createRoot(this.dom);
+ this.root.render(
+ <DashFieldViewInternal
+ node={node}
+ unclickable={this.unclickable}
+ getPos={getPos}
+ fieldKey={node.attrs.fieldKey}
+ docId={node.attrs.docId}
+ width={node.attrs.width}
+ height={node.attrs.height}
+ hideKey={node.attrs.hideKey}
+ editable={node.attrs.editable}
+ tbox={tbox}
+ />
+ );
}
destroy() {
- ReactDOM.unmountComponentAtNode(this.dom);
+ this.root.unmount();
+ }
+ deselectNode() {
+ this.dom.classList.remove('ProseMirror-selectednode');
+ }
+ selectNode() {
+ this.dom.classList.add('ProseMirror-selectednode');
}
- selectNode() {}
}
interface IDashFieldViewInternal {
fieldKey: string;
- docid: string;
+ docId: string;
hideKey: boolean;
tbox: FormattedTextBox;
width: number;
height: number;
+ editable: boolean;
+ node: any;
+ getPos: any;
+ unclickable: () => boolean;
}
@observer
@@ -74,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;
}
@@ -116,7 +146,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
return (
<span
className="dashFieldView-fieldSpan"
- contentEditable={true}
+ contentEditable={!this.props.unclickable()}
style={{ display: strVal.length < 2 ? 'inline-block' : undefined }}
suppressContentEditableWarning={true}
defaultValue={strVal}
@@ -125,7 +155,13 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
r?.addEventListener('blur', e => r && this.updateText(r.textContent!, false));
r?.addEventListener(
'pointerdown',
- action(e => e.stopPropagation())
+ action(e => {
+ // 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;
+ this.props.tbox.EditorView!.dispatch(this.props.tbox.EditorView!.state.tr.setSelection(new NodeSelection(this.props.tbox.EditorView!.state.doc.resolve(this.props.getPos()))));
+ // FormattedTextBoxComment.update(this.props.tbox, this.props.tbox.EditorView!, undefined, target?.dataset?.targethrefs, target?.dataset.linkdoc);
+ // e.stopPropagation();
+ })
);
}}>
{strVal}
@@ -138,6 +174,10 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
// we need to handle all key events on the input span or else they will propagate to prosemirror.
@action
fieldSpanKeyDown = (e: KeyboardEvent, span: HTMLSpanElement) => {
+ if (e.key === 'c' && (e.ctrlKey || e.metaKey)) {
+ navigator.clipboard.writeText(window.getSelection()?.toString() || '');
+ return;
+ }
if (e.key === 'Enter') {
// handle the enter key by "submitting" the current text to Dash's database.
this.updateText(span.textContent!, true);
@@ -153,6 +193,9 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
}
e.preventDefault(); //prevent default so that all the text in the prosemirror text box isn't selected
}
+ if (!this.props.editable) {
+ e.preventDefault();
+ }
e.stopPropagation(); // we need to handle all events or else they will propagate to prosemirror.
};
@@ -160,7 +203,6 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
updateText = (nodeText: string, forceMatch: boolean) => {
if (nodeText) {
const newText = nodeText.startsWith(':=') || nodeText.startsWith('=:=') ? ':=-computed-' : nodeText;
-
// look for a document whose id === the fieldKey being displayed. If there's a match, then that document
// holds the different enumerated values for the field in the titles of its collected documents.
// if there's a partial match from the start of the input text, complete the text --- TODO: make this an auto suggest box and select from a drop down.
@@ -178,7 +220,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
} else {
if (Number(newText).toString() === newText) {
if (this._fieldKey.startsWith('_')) Doc.Layout(this._textBoxDoc)[this._fieldKey] = Number(newText);
- Doc.SetInPlace(this._dashDoc!, this._fieldKey, newText, true);
+ 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) {
@@ -207,7 +249,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
list.map(c => c.heading).indexOf(this._fieldKey) === -1 && list.push(new SchemaHeaderField(this._fieldKey, '#f1efeb'));
list.map(c => c.heading).indexOf('text') === -1 && list.push(new SchemaHeaderField('text', '#f1efeb'));
alias._pivotField = this._fieldKey.startsWith('#') ? '#' : this._fieldKey;
- this.props.tbox.props.addDocTab(alias, 'add:right');
+ this.props.tbox.props.addDocTab(alias, OpenWhere.addRight);
}
};
@@ -266,14 +308,12 @@ export class DashFieldViewMenu extends AntimodeMenu<AntimodeMenuProps> {
document.addEventListener('pointerdown', hideMenu, true);
};
render() {
- const buttons = [
+ 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>,
- ];
-
- return this.getElement(buttons);
+ </Tooltip>
+ );
}
}