aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/SidebarAnnos.tsx34
-rw-r--r--src/client/views/linking/LinkMenuItem.tsx1
-rw-r--r--src/client/views/nodes/LinkAnchorBox.tsx1
-rw-r--r--src/client/views/nodes/LinkDocPreview.tsx2
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.scss9
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx65
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx7
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx14
-rw-r--r--src/client/views/nodes/formattedText/RichTextRules.ts2
-rw-r--r--src/client/views/nodes/formattedText/marks_rts.ts4
10 files changed, 71 insertions, 68 deletions
diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index 78480da03..c285b2e34 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -67,7 +67,6 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
_height: 50,
_fitWidth: true,
_autoHeight: true,
- _isLinkButton: true,
_fontSize: StrCast(Doc.UserDoc().fontSize),
_fontFamily: StrCast(Doc.UserDoc().fontFamily),
});
@@ -84,20 +83,33 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
return {
type: 'dashField',
attrs: { fieldKey: key, docid: '', hideKey: false, editable: true },
- marks: [
- { type: 'pFontSize', attrs: { fontSize: '12px' } },
- { type: 'pFontFamily', attrs: { family: 'Arial' } },
- { type: 'pFontColor', attrs: { color: 'black' } },
- { type: 'strong' },
- { type: 'user_mark', attrs: { userid: Doc.CurrentUserEmail, modified: 0 } },
- ],
+ marks: [{ type: 'pFontSize', attrs: { fontSize: '12px' } }, { type: 'strong' }, { type: 'user_mark', attrs: { userid: Doc.CurrentUserEmail, modified: 0 } }],
};
});
- const textLines = [
+
+ const textLines: any = [
{
type: 'paragraph',
attrs: { align: null, color: null, id: null, indent: null, inset: null, lineSpacing: null, paddingBottom: null, paddingTop: null },
- content: [{ type: 'dashField', attrs: { fieldKey: 'text', docid: anchor[Id], hideKey: true, editable: false } }],
+ content: [
+ {
+ type: 'dashField',
+ marks: [
+ {
+ type: 'linkAnchor',
+ attrs: {
+ allAnchors: [{ href: `/doc/${target[Id]}`, title: 'Anchored Selection', noPreview: true, anchorId: `${target[Id]}` }],
+ location: 'add:right',
+ title: 'Anchored Selection',
+ docref: false,
+ },
+ },
+ { type: 'pFontSize', attrs: { fontSize: '8px' } },
+ { type: 'em' },
+ ],
+ attrs: { fieldKey: 'text', docid: anchor[Id], hideKey: true, editable: false },
+ },
+ ],
},
{ type: 'paragraph', attrs: { align: null, color: null, id: null, indent: null, inset: null, lineSpacing: null, paddingBottom: null, paddingTop: null } },
];
@@ -118,7 +130,7 @@ export class SidebarAnnos extends React.Component<FieldViewProps & ExtraProps> {
''
);
this.addDocument(target);
- this._stackRef.current?.focusDocument(target, {});
+ setTimeout(() => this._stackRef.current?.focusDocument(target, {}));
return target;
};
makeDocUnfiltered = (doc: Doc) => {
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 3f9db2612..387e0e3d5 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -155,6 +155,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
linkDoc: this.props.linkDoc,
showHeader: false,
location: [this._drag.current?.getBoundingClientRect().right ?? 100, this._drag.current?.getBoundingClientRect().top ?? e.clientY],
+ noPreview: false,
})
}
onPointerDown={this.onLinkButtonDown}>
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index 5102eae51..d6cf79f87 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -144,6 +144,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() {
linkDoc: this.rootDoc,
showHeader: true,
location: [e.clientX, e.clientY + 20],
+ noPreview: false,
})
}
onPointerDown={this.onPointerDown}
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 27e79a83b..0e66214d1 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -26,6 +26,7 @@ interface LinkDocPreviewProps {
location: number[];
hrefs?: string[];
showHeader?: boolean;
+ noPreview?: boolean;
}
@observer
export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
@@ -111,6 +112,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
this._targetDoc = /*linkTarget?.type === DocumentType.MARKER &&*/ linkTarget?.annotationOn ? Cast(linkTarget.annotationOn, Doc, null) ?? linkTarget : linkTarget;
}
this._toolTipText = '';
+ if (LinkDocPreview.LinkInfo?.noPreview) this.followLink();
}
})
);
diff --git a/src/client/views/nodes/formattedText/DashFieldView.scss b/src/client/views/nodes/formattedText/DashFieldView.scss
index c36e6804b..f17579853 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.scss
+++ b/src/client/views/nodes/formattedText/DashFieldView.scss
@@ -1,3 +1,5 @@
+@import '../../global/globalCssVariables';
+
.dashFieldView {
position: relative;
display: inline-flex;
@@ -22,7 +24,7 @@
position: relative;
display: inline-block;
font-weight: normal;
- background: rgba(0,0,0,0.1);
+ background: rgba(0, 0, 0, 0.1);
}
.dashFieldView-fieldSpan {
min-width: 8px;
@@ -31,11 +33,12 @@
padding-left: 2px;
display: inline-block;
background-color: rgba(155, 155, 155, 0.24);
- font-weight: bold;
span {
min-width: 100%;
display: inline-block;
}
}
}
- \ No newline at end of file
+.ProseMirror-selectedNode {
+ outline: solid 1px $light-blue !important;
+}
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index f088b39d1..fbcf25215 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -16,21 +16,20 @@ 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 { FormattedTextBoxComment } from './FormattedTextBoxComment';
export class DashFieldView {
dom: HTMLDivElement; // container for label and value
root: any;
constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) {
- const { boolVal, strVal } = DashFieldViewInternal.fieldContent(tbox.props.Document, tbox.rootDoc, node.attrs.fieldKey);
-
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.contentEditable = 'true';
this.dom.onkeypress = function (e: any) {
e.stopPropagation();
};
@@ -45,12 +44,20 @@ export class DashFieldView {
};
this.root = ReactDOM.createRoot(this.dom);
- this.root.render(<DashFieldViewInternal 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} />);
+ this.root.render(
+ <DashFieldViewInternal node={node} 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() {
//this.root.unmount();
}
- selectNode() {}
+ deselectNode() {
+ this.dom.classList.remove('ProseMirror-selectednode');
+ }
+ selectNode() {
+ this.dom.classList.add('ProseMirror-selectednode');
+ console.log('SELECT');
+ }
}
interface IDashFieldViewInternal {
@@ -61,6 +68,8 @@ interface IDashFieldViewInternal {
width: number;
height: number;
editable: boolean;
+ node: any;
+ getPos: any;
}
@observer
@@ -127,7 +136,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}
@@ -162,42 +177,6 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
updateText = (nodeText: string, forceMatch: boolean) => {
if (nodeText) {
const newText = nodeText.startsWith(':=') || nodeText.startsWith('=:=') ? ':=-computed-' : nodeText;
-
- // const json = {
- // doc: {
- // type: 'doc',
- // content: [
- // {
- // type: 'paragraph',
- // attrs: { align: null, color: null, id: null, indent: null, inset: null, lineSpacing: null, paddingBottom: null, paddingTop: null },
- // content: [{ type: 'dashField', attrs: { fieldKey: 'text', docid: '7e02a420-8add-49b0-ad20-54680567575f', hideKey: true, editable: false }, marks: [{ type: 'strong' }] }],
- // },
- // {
- // type: 'paragraph',
- // attrs: { align: null, color: null, id: null, indent: null, inset: null, lineSpacing: null, paddingBottom: null, paddingTop: null },
- // content: [{ type: 'text', marks: [{ type: 'user_mark', attrs: { userid: 'mart@bar.com', modified: 1667334077 } }] }],
- // },
- // ],
- // },
- // };
-
- // const json = {
- // doc: {
- // type: 'doc',
- // content: [
- // {
- // type: 'paragraph',
- // attrs: { align: null, color: null, id: null, indent: null, inset: null, lineSpacing: null, paddingBottom: null, paddingTop: null },
- // content: [{ type: 'dashField', attrs: { fieldKey: 'hello', docid: '', hideKey: true, editable: true }, marks: [{ type: 'strong' }, { type: 'user_mark', attrs: { userid: 'mart@bar.com', modified: 1667334006 } }] }],
- // },
- // {
- // type: 'paragraph',
- // attrs: { align: null, color: null, id: null, indent: null, inset: null, lineSpacing: null, paddingBottom: null, paddingTop: null },
- // content: [{ type: 'text', marks: [{ type: 'user_mark', attrs: { userid: 'mart@bar.com', modified: 1667334088 } }] }],
- // },
- // ],
- // },
- // };
// 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.
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index e9f59f17d..4378c10f7 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -393,13 +393,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
const newAutoLinks = new Set<Doc>();
const oldAutoLinks = DocListCast(this.props.Document.links).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;
const t = this._editorView.state.selection.to;
var tr = this._editorView.state.tr as any;
const autoAnch = this._editorView.state.schema.marks.autoLinkAnchor;
tr = tr.removeMark(0, tr.doc.content.size, autoAnch);
DocListCast(Doc.MyPublishedDocs.data).forEach(term => (tr = this.hyperlinkTerm(tr, term, newAutoLinks)));
- tr = tr.setSelection(new TextSelection(tr.doc.resolve(f), tr.doc.resolve(t)));
+ tr = tr.setSelection(isNodeSel && false ? new NodeSelection(tr.doc.resolve(f)) : new TextSelection(tr.doc.resolve(f), tr.doc.resolve(t)));
this._editorView?.dispatch(tr);
}
oldAutoLinks.filter(oldLink => !newAutoLinks.has(oldLink) && oldLink.anchor2 !== this.rootDoc).forEach(LinkManager.Instance.deleteLink);
@@ -1485,7 +1486,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
document.removeEventListener('pointermove', this.onSelectMove);
};
onPointerUp = (e: React.PointerEvent): void => {
- if (!this._editorView?.state.selection.empty && FormattedTextBox._canAnnotate && !(e.nativeEvent as any).dash) this.setupAnchorMenu();
+ if (!this._editorView?.state.selection.empty && !(this._editorView?.state.selection instanceof NodeSelection) && FormattedTextBox._canAnnotate && !(e.nativeEvent as any).dash) this.setupAnchorMenu();
if (!this._downEvent) return;
this._downEvent = false;
if (this.props.isContentActive(true) && !(e.nativeEvent as any).dash) {
@@ -1494,7 +1495,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
!this.props.isSelected(true) && editor.dispatch(editor.state.tr.setSelection(new TextSelection(editor.state.doc.resolve(pcords?.pos || 0))));
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);
+ FormattedTextBoxComment.update(this, editor, undefined, target?.dataset?.targethrefs, target?.dataset.linkdoc, target?.dataset.noPreview);
}
if (e.button === 0 && this.props.isSelected(true) && !e.altKey) {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index bdf59863b..e7ca26d5c 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -1,5 +1,5 @@
import { Mark, ResolvedPos } from 'prosemirror-model';
-import { EditorState } from 'prosemirror-state';
+import { EditorState, NodeSelection } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';
import { Doc } from '../../../../fields/Doc';
import { DocServer } from '../../../DocServer';
@@ -92,7 +92,7 @@ export class FormattedTextBoxComment {
FormattedTextBoxComment.tooltip.style.display = '';
}
- static update(textBox: FormattedTextBox, view: EditorView, lastState?: EditorState, hrefs: string = '', linkDoc: string = '') {
+ static update(textBox: FormattedTextBox, view: EditorView, lastState?: EditorState, hrefs: string = '', linkDoc: string = '', noPreview: boolean = false) {
FormattedTextBoxComment.textBox = textBox;
if (hrefs || !lastState?.doc.eq(view.state.doc) || !lastState?.selection.eq(view.state.selection)) {
FormattedTextBoxComment.setupPreview(
@@ -102,12 +102,13 @@ export class FormattedTextBoxComment {
?.trim()
.split(' ')
.filter(h => h),
- linkDoc
+ linkDoc,
+ noPreview
);
}
}
- static setupPreview(view: EditorView, textBox: FormattedTextBox, hrefs?: string[], linkDoc?: string) {
+ static setupPreview(view: EditorView, textBox: FormattedTextBox, hrefs?: string[], linkDoc?: string, noPreview?: boolean) {
const state = view.state;
// this section checks to see if the insertion point is over text entered by a different user. If so, it sets ths comment text to indicate the user and the modification date
if (state.selection.$from) {
@@ -130,8 +131,8 @@ export class FormattedTextBoxComment {
if (state.selection.$from && hrefs?.length) {
const nbef = findStartOfMark(state.selection.$from, view, findLinkMark);
const naft = findEndOfMark(state.selection.$from, view, findLinkMark) || nbef;
- nbef &&
- naft &&
+ //nbef &&
+ naft &&
LinkDocPreview.SetLinkInfo({
docProps: textBox.props,
linkSrc: textBox.rootDoc,
@@ -139,6 +140,7 @@ export class FormattedTextBoxComment {
location: (pos => [pos.left, pos.top + 25])(view.coordsAtPos(state.selection.from - Math.max(0, nbef - 1))),
hrefs,
showHeader: true,
+ noPreview,
});
}
}
diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts
index dc5d8ada8..e3c67ad2e 100644
--- a/src/client/views/nodes/formattedText/RichTextRules.ts
+++ b/src/client/views/nodes/formattedText/RichTextRules.ts
@@ -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: true });
+ 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);
}),
diff --git a/src/client/views/nodes/formattedText/marks_rts.ts b/src/client/views/nodes/formattedText/marks_rts.ts
index 00c41e187..4206a1006 100644
--- a/src/client/views/nodes/formattedText/marks_rts.ts
+++ b/src/client/views/nodes/formattedText/marks_rts.ts
@@ -75,6 +75,7 @@ export const marks: { [index: string]: MarkSpec } = {
allAnchors: { default: [] as { href: string; title: string; anchorId: string }[] },
location: { default: null },
title: { default: null },
+ noPreview: { default: false },
docref: { default: false }, // flags whether the linked text comes from a document within Dash. If so, an attribution label is appended after the text
},
inclusive: false,
@@ -85,6 +86,7 @@ export const marks: { [index: string]: MarkSpec } = {
return {
location: dom.getAttribute('location'),
title: dom.getAttribute('title'),
+ noPreview: dom.getAttribute('noPreview'),
};
},
},
@@ -111,7 +113,7 @@ export const marks: { [index: string]: MarkSpec } = {
['br'],
]
: //node.attrs.allLinks.length === 1 ?
- ['a', { class: anchorids, 'data-targethrefs': targethrefs, title: node.attrs.title, location: node.attrs.location, style: `text-decoration: underline` }, 0];
+ ['a', { class: anchorids, 'data-targethrefs': targethrefs, title: node.attrs.title, noPreview: node.attrs.noPreview, location: node.attrs.location, style: `text-decoration: underline` }, 0];
// ["div", { class: "prosemirror-anchor" },
// ["span", { class: "prosemirror-linkBtn" },
// ["a", { ...node.attrs, class: linkids, "data-targetids": targetids, title: `${node.attrs.title}` }, 0],