diff options
Diffstat (limited to 'src')
18 files changed, 112 insertions, 58 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 58aec6173..04ab514f0 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -52,6 +52,7 @@ import { DocumentBox } from "../views/nodes/DocumentBox"; import { InkingStroke } from "../views/InkingStroke"; import { InkField } from "../../new_fields/InkField"; import { InkingControl } from "../views/InkingControl"; +import { RichTextField } from "../../new_fields/RichTextField"; const requestImageSize = require('../util/request-image-size'); const path = require('path'); @@ -72,6 +73,7 @@ export interface DocumentOptions { _gridGap?: number; // gap between items in masonry view _xMargin?: number; // gap between left edge of document and start of masonry/stacking layouts _yMargin?: number; // gap between top edge of dcoument and start of masonry/stacking layouts + _textTemplate?: RichTextField; // template used by a formattedTextBox to create a text box to render x?: number; y?: number; z?: number; @@ -441,8 +443,8 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COLOR), "", options); } - export function TextDocument(options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocumentType.TEXT), "", options); + export function TextDocument(text: string, options: DocumentOptions = {}) { + return InstanceFromProto(Prototypes.get(DocumentType.TEXT), text, options); } export function InkDocument(color: string, tool: number, strokeWidth: number, points: { X: number, Y: number }[], options: DocumentOptions = {}) { @@ -703,7 +705,7 @@ export namespace Docs { created = Docs.Create.StackingDocument(DocListCast(field), resolved); layout = CollectionView.LayoutString; } else { - created = Docs.Create.TextDocument({ ...{ _width: 200, _height: 25, _autoHeight: true }, ...resolved }); + created = Docs.Create.TextDocument("", { ...{ _width: 200, _height: 25, _autoHeight: true }, ...resolved }); layout = FormattedTextBox.LayoutString; } created.layout = layout?.(fieldKey); diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index fa7f63965..3394cb93d 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -332,7 +332,7 @@ export namespace DictationManager { ["new outline", { action: (target: DocumentView) => { - const newBox = Docs.Create.TextDocument({ _width: 400, _height: 200, title: "My Outline", _autoHeight: true }); + const newBox = Docs.Create.TextDocument("", { _width: 400, _height: 200, title: "My Outline", _autoHeight: true }); const proto = newBox.proto!; const prompt = "Press alt + r to start dictating here..."; const head = 3; diff --git a/src/client/util/RichTextRules.ts b/src/client/util/RichTextRules.ts index 02b7502d8..bc8a0abb1 100644 --- a/src/client/util/RichTextRules.ts +++ b/src/client/util/RichTextRules.ts @@ -2,7 +2,7 @@ import { textblockTypeInputRule, smartQuotes, emDash, ellipsis, InputRule } from import { schema } from "./RichTextSchema"; import { wrappingInputRule } from "./prosemirrorPatches"; import { NodeSelection, TextSelection } from "prosemirror-state"; -import { NumCast, Cast } from "../../new_fields/Types"; +import { StrCast, Cast } from "../../new_fields/Types"; import { Doc } from "../../new_fields/Doc"; import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; import { Docs, DocUtils } from "../documents/Documents"; @@ -72,6 +72,19 @@ export const inpRules = { // make current selection a hyperlink portal (assumes % was used to initiate an EnteringStyle mode) new InputRule( + new RegExp(/!$/), + (state, match, start, end) => { + if (state.selection.to === state.selection.from || !(schema as any).EnteringStyle) return null; + const value = state.doc.textBetween(start, end); + + const node = (state.doc.resolve(start) as any).nodeAfter; + const sm = state.storedMarks || undefined; + const fieldView = state.schema.nodes.dashField.create({ fieldKey: StrCast(value) }); + const replaced = node ? state.tr.replaceRangeWith(start, end, fieldView).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; + return replaced.doc.nodeSize > end - 2 ? replaced.setSelection(new TextSelection(replaced.doc.resolve(end - 2))) : replaced; + }), + // make current selection a hyperlink portal (assumes % was used to initiate an EnteringStyle mode) + new InputRule( new RegExp(/@$/), (state, match, start, end) => { if (state.selection.to === state.selection.from || !(schema as any).EnteringStyle) return null; @@ -196,7 +209,7 @@ export const inpRules = { new InputRule( new RegExp(/%#$/), (state, match, start, end) => { - const target = Docs.Create.TextDocument({ _width: 75, _height: 35, backgroundColor: "yellow", annotationOn: FormattedTextBox.FocusedBox!.dataDoc, _autoHeight: true, fontSize: 9, title: "inline comment" }); + const target = Docs.Create.TextDocument("", { _width: 75, _height: 35, backgroundColor: "yellow", annotationOn: FormattedTextBox.FocusedBox!.dataDoc, _autoHeight: true, fontSize: 9, title: "inline comment" }); const node = (state.doc.resolve(start) as any).nodeAfter; const newNode = schema.nodes.dashComment.create({ docid: target[Id] }); const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: "dashDoc", docid: target[Id], float: "right" }); diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index d64098e5f..21916e3d6 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -8,7 +8,7 @@ import { EditorState, NodeSelection, TextSelection, Plugin } from "prosemirror-s import { StepMap } from "prosemirror-transform"; import { EditorView } from "prosemirror-view"; import * as ReactDOM from 'react-dom'; -import { Doc, WidthSym, HeightSym } from "../../new_fields/Doc"; +import { Doc, WidthSym, HeightSym, DataSym, Field } from "../../new_fields/Doc"; import { emptyFunction, returnEmptyString, returnFalse, returnOne, Utils } from "../../Utils"; import { DocServer } from "../DocServer"; import { DocumentView } from "../views/nodes/DocumentView"; @@ -16,7 +16,7 @@ import { DocumentManager } from "./DocumentManager"; import ParagraphNodeSpec from "./ParagraphNodeSpec"; import { Transform } from "./Transform"; import React = require("react"); -import { BoolCast, NumCast, Cast } from "../../new_fields/Types"; +import { BoolCast, NumCast, StrCast } from "../../new_fields/Types"; import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; const blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"], @@ -175,6 +175,19 @@ export const nodes: { [index: string]: NodeSpec } = { } }, + dashField: { + inline: true, + attrs: { + fieldKey: { default: "" }, + }, + group: "inline", + draggable: false, + toDOM(node) { + const attrs = { style: `width: ${node.attrs.width}, height: ${node.attrs.height}` }; + return ["div", { ...node.attrs, ...attrs }]; + } + }, + video: { inline: true, attrs: { @@ -799,6 +812,42 @@ export class DashDocView { } } +export class DashFieldView { + _fieldWrapper: HTMLDivElement; + _labelSpan: HTMLSpanElement; + _fieldSpan: HTMLSpanElement; + _reactionDisposer: IReactionDisposer | undefined; + _textBoxDoc: Doc; + + constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) { + this._textBoxDoc = tbox.props.Document; + this._fieldWrapper = document.createElement("div"); + this._fieldWrapper.style.width = node.attrs.width; + this._fieldWrapper.style.height = node.attrs.height; + this._fieldWrapper.style.position = "relative"; + this._fieldWrapper.style.display = "inline"; + + this._fieldSpan = document.createElement("span"); + this._fieldSpan.style.position = "relative"; + this._fieldSpan.style.display = "inline"; + + this._labelSpan = document.createElement("span"); + this._labelSpan.style.position = "relative"; + this._labelSpan.style.display = "inline"; + this._labelSpan.style.fontWeight = "bold"; + this._labelSpan.style.fontSize = "larger"; + this._labelSpan.innerHTML = `${node.attrs.fieldKey}: `; + this._reactionDisposer && this._reactionDisposer(); + this._reactionDisposer = reaction(() => this._textBoxDoc[DataSym][node.attrs.fieldKey], fval => this._fieldSpan.innerHTML = Field.toString(fval as Field), { fireImmediately: true }); + this._fieldWrapper.appendChild(this._labelSpan); + this._fieldWrapper.appendChild(this._fieldSpan); + (this as any).dom = this._fieldWrapper; + } + destroy() { + this._reactionDisposer && this._reactionDisposer(); + } +} + export class OrderedListView { update(node: any) { return false; // if attr's of an ordered_list (e.g., bulletStyle) change, return false forces the dom node to be recreated which is necessary for the bullet labels to update diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index b1c84667d..c011adb20 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -49,7 +49,7 @@ export class PreviewCursor extends React.Component<{}> { } // creates text document - return PreviewCursor._addLiveTextDoc(Docs.Create.TextDocument({ + return PreviewCursor._addLiveTextDoc(Docs.Create.TextDocument("", { _width: 500, limitHeight: 400, _autoHeight: true, diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index 57b091ce4..e25a2f5eb 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -136,7 +136,7 @@ export class CollectionMasonryViewFieldRow extends React.Component<CMVFieldRowPr addDocument = (value: string, shiftDown?: boolean) => { this._createAliasSelected = false; const key = StrCast(this.props.parent.props.Document.sectionFilter); - const newDoc = Docs.Create.TextDocument({ _height: 18, _width: 200, title: value }); + const newDoc = Docs.Create.TextDocument("", { _height: 18, _width: 200, title: value }); newDoc[key] = this.getValue(this.props.heading); return this.props.parent.props.addDocument(newDoc); } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 9ecb8dc43..a35c945b9 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -477,7 +477,7 @@ export class SchemaTable extends React.Component<SchemaTableProps> { @undoBatch createRow = () => { - const newDoc = Docs.Create.TextDocument({ title: "", _width: 100, _height: 30 }); + const newDoc = Docs.Create.TextDocument("", { title: "", _width: 100, _height: 30 }); this.props.addDocument(newDoc); } diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 0960b0e96..dabc14445 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -152,7 +152,7 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC } this._createAliasSelected = false; const key = StrCast(this.props.parent.props.Document.sectionFilter); - const newDoc = Docs.Create.TextDocument({ _height: 18, _width: 200, documentText: "@@@" + value, title: value, _autoHeight: true }); + const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, title: value, _autoHeight: true }); newDoc[key] = this.getValue(this.props.heading); const maxHeading = this.props.docList.reduce((maxHeading, doc) => NumCast(doc.heading) > maxHeading ? NumCast(doc.heading) : maxHeading, 0); const heading = maxHeading === 0 || this.props.docList.length === 0 ? 1 : maxHeading === 1 ? 2 : 3; diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index d1a5bed1e..db3fde797 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -224,7 +224,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { this.props.addDocument && this.props.addDocument(Docs.Create.WebDocument(href, { ...options, title: href })); } } else if (text) { - this.props.addDocument && this.props.addDocument(Docs.Create.TextDocument({ ...options, _width: 100, _height: 25, documentText: "@@@" + text })); + this.props.addDocument && this.props.addDocument(Docs.Create.TextDocument(text, { ...options, _width: 100, _height: 25 })); } return; } @@ -262,7 +262,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { } let matches: RegExpExecArray | null; if ((matches = /(https:\/\/)?docs\.google\.com\/document\/d\/([^\\]+)\/edit/g.exec(text)) !== null) { - const newBox = Docs.Create.TextDocument({ ...options, _width: 400, _height: 200, title: "Awaiting title from Google Docs..." }); + const newBox = Docs.Create.TextDocument("", { ...options, _width: 400, _height: 200, title: "Awaiting title from Google Docs..." }); const proto = newBox.proto!; const documentId = matches[2]; proto[GoogleRef] = documentId; @@ -333,7 +333,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { Promise.all(promises).finally(() => { completed && completed(); batch.end(); }); } else { if (text && !text.includes("https://")) { - this.props.addDocument(Docs.Create.TextDocument({ ...options, documentText: "@@@" + text, _width: 400, _height: 315 })); + this.props.addDocument(Docs.Create.TextDocument(text, { ...options, _width: 400, _height: 315 })); } batch.end(); } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 485abf8b9..2208de264 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -33,6 +33,7 @@ import { CollectionSubView } from "./CollectionSubView"; import "./CollectionTreeView.scss"; import React = require("react"); import { CollectionViewType } from './CollectionView'; +import { RichTextField } from '../../../new_fields/RichTextField'; export interface TreeViewProps { @@ -634,18 +635,18 @@ export class CollectionTreeView extends CollectionSubView(Document) { const { TextDocument, ImageDocument, MulticolumnDocument, TreeDocument } = Docs.Create; const { Document } = this.props; const fallbackImg = "http://www.cs.brown.edu/~bcz/face.gif"; + const detailedTemplate = `{ "doc": { "type": "doc", "content": [ { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "short_description" } } ] }, { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "year" } } ] }, { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "company" } } ] } ] }, "selection":{"type":"text","anchor":1,"head":1},"storedMarks":[] }`; const detailedLayout = Docs.Create.StackingDocument([ ImageDocument(fallbackImg, { title: "activeHero" }), MulticolumnDocument([], { title: "data", _height: 100, onChildClick: ScriptField.MakeFunction( `containingCollection.resolvedDataDoc.activeHero = copyField(this.data); - containingCollection.resolvedDataDoc.activeHero["activeHero-nativeWidth"] = copyField(this.data["data-nativeWidth"]); - containingCollection.resolvedDataDoc.activeHero["activeHero-nativeHeight"] = copyField(this.data["data-nativeHeight"]); + containingCollection.resolvedDataDoc.activeHero["activeHero-nativeWidth"] = copyField(this.data["data-nativeWidth"]); + containingCollection.resolvedDataDoc.activeHero["activeHero-nativeHeight"] = copyField(this.data["data-nativeHeight"]); `, { containingCollection: Doc.name }) }), - TextDocument({ title: "short_description", _autoHeight: true }), - ...["year", "company", "degrees_of_freedom"].map(key => TextDocument({ title: key, _height: 30 })) + TextDocument("", { title: "details", _autoHeight: true, _textTemplate: new RichTextField(detailedTemplate, "short_description year company") }) ], { _chromeStatus: "disabled", title: "detailed layout stack" }); detailedLayout.isTemplateDoc = makeTemplate(detailedLayout); @@ -733,7 +734,7 @@ Scripting.addGlobal(function readFacetData(layoutDoc: Doc, dataDoc: Doc, dataKey }; const capturedVariables = { layoutDoc, facetHeader }; return new List<Doc>(Array.from(facetValues).sort().map(facetValue => { - const value = Docs.Create.TextDocument({ title: facetValue.toString() }); + const value = Docs.Create.TextDocument("", { title: facetValue.toString() }); value.treeViewChecked = ComputedField.MakeFunction(text, params, { ...capturedVariables, facetValue }); return value; })); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 7aa9d4922..70f8a0e73 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -921,7 +921,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { description: "Add Note ...", subitems: DocListCast((CurrentUserUtils.UserDocument.noteTypes as Doc).data).map((note, i) => ({ description: (i + 1) + ": " + StrCast(note.title), - event: (args: { x: number, y: number }) => this.addLiveTextBox(Docs.Create.TextDocument({ _width: 200, _height: 100, x: this.getTransform().transformPoint(args.x, args.y)[0], y: this.getTransform().transformPoint(args.x, args.y)[1], _autoHeight: true, layout: note, title: StrCast(note.title) })), + event: (args: { x: number, y: number }) => this.addLiveTextBox(Docs.Create.TextDocument("", { _width: 200, _height: 100, x: this.getTransform().transformPoint(args.x, args.y)[0], y: this.getTransform().transformPoint(args.x, args.y)[1], _autoHeight: true, layout: note, title: StrCast(note.title) })), icon: "eye" })) as ContextMenuProps[], icon: "eye" diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 741712b6e..6a1590b8e 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -84,7 +84,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque } ns.map(line => { const indent = line.search(/\S|$/); - const newBox = Docs.Create.TextDocument({ _width: 200, _height: 35, x: x + indent / 3 * 10, y: y, documentText: "@@@" + line, title: line }); + const newBox = Docs.Create.TextDocument(line, { _width: 200, _height: 35, x: x + indent / 3 * 10, y: y, title: line }); this.props.addDocument(newBox); y += 40 * this.props.getTransform().Scale; }); @@ -101,10 +101,10 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque }); } else if (!e.ctrlKey) { this.props.addLiveTextDocument( - Docs.Create.TextDocument({ _width: 200, _height: 100, x: x, y: y, _autoHeight: true, title: "-typed text-" })); + Docs.Create.TextDocument("", { _width: 200, _height: 100, x: x, y: y, _autoHeight: true, title: "-typed text-" })); } else if (e.keyCode > 48 && e.keyCode <= 57) { const notes = DocListCast((CurrentUserUtils.UserDocument.noteTypes as Doc).data); - const text = Docs.Create.TextDocument({ _width: 200, _height: 100, x: x, y: y, _autoHeight: true, title: "-typed text-" }); + const text = Docs.Create.TextDocument("", { _width: 200, _height: 100, x: x, y: y, _autoHeight: true, title: "-typed text-" }); text.layout = notes[(e.keyCode - 49) % notes.length]; this.props.addLiveTextDocument(text); } @@ -374,7 +374,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque return d; }); newCollection._chromeStatus = "disabled"; - const summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, _width: 300, _height: 100, _autoHeight: true, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" }); + const summary = Docs.Create.TextDocument("", { x: bounds.left, y: bounds.top, _width: 300, _height: 100, _autoHeight: true, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" }); Doc.GetProto(summary).summarizedDocs = new List<Doc>([newCollection]); newCollection.x = bounds.left + bounds.width; Doc.GetProto(newCollection).summaryDoc = summary; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c8b1f9794..609eb689e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -531,7 +531,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu let fieldTemplate: Doc; switch (doc.type) { case DocumentType.TEXT: - fieldTemplate = Docs.Create.TextDocument(options); + fieldTemplate = Docs.Create.TextDocument("", options); break; case DocumentType.PDF: fieldTemplate = Docs.Create.PdfDocument("http://www.msn.com", options); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index b794ad0c5..fab267358 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -12,7 +12,7 @@ import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from " import { ReplaceStep } from 'prosemirror-transform'; import { EditorView } from "prosemirror-view"; import { DateField } from '../../../new_fields/DateField'; -import { Doc, DocListCastAsync, Opt, WidthSym, HeightSym, DataSym } from "../../../new_fields/Doc"; +import { Doc, DocListCastAsync, Opt, WidthSym, HeightSym, DataSym, Field } from "../../../new_fields/Doc"; import { Copy, Id } from '../../../new_fields/FieldSymbols'; import { RichTextField } from "../../../new_fields/RichTextField"; import { RichTextUtils } from '../../../new_fields/RichTextUtils'; @@ -27,7 +27,7 @@ import { DictationManager } from '../../util/DictationManager'; import { DragManager } from "../../util/DragManager"; import buildKeymap from "../../util/ProsemirrorExampleTransfer"; import { inpRules } from "../../util/RichTextRules"; -import { DashDocCommentView, FootnoteView, ImageResizeView, DashDocView, OrderedListView, schema, SummaryView } from "../../util/RichTextSchema"; +import { DashDocCommentView, FootnoteView, ImageResizeView, DashDocView, OrderedListView, schema, SummaryView, DashFieldView } from "../../util/RichTextSchema"; import { SelectionManager } from "../../util/SelectionManager"; import { undoBatch, UndoManager } from "../../util/UndoManager"; import { DocAnnotatableComponent, DocAnnotatableProps } from "../DocComponent"; @@ -534,7 +534,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & () => this.tryUpdateHeight() ); - this.setupEditor(this.config, this.dataDoc, this.props.fieldKey); + this.setupEditor(this.config, this.props.fieldKey); this._searchReactionDisposer = reaction(() => this.layoutDoc.searchMatch, search => search ? this.highlightSearchTerms([Doc.SearchQuery()]) : this.unhighlightSearchTerms(), @@ -736,28 +736,18 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } } - private setupEditor(config: any, doc: Doc, fieldKey: string) { - const field = doc ? Cast(doc[fieldKey], RichTextField) : undefined; - let startup = StrCast(doc.documentText); - startup = startup.startsWith("@@@") ? startup.replace("@@@", "") : ""; - if (!field && doc) { - const text = StrCast(doc[fieldKey]); - if (text) { - startup = text; - } else if (Cast(doc[fieldKey], "number")) { - startup = NumCast(doc[fieldKey], 99).toString(); - } - } + private setupEditor(config: any, fieldKey: string) { + const rtfField = Cast(this.props.Document._textTemplate || this.dataDoc[fieldKey], RichTextField); if (this.ProseRef) { const self = this; - this._editorView && this._editorView.destroy(); + this._editorView?.destroy(); this._editorView = new EditorView(this.ProseRef, { - state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config), + state: rtfField?.Data ? EditorState.fromJSON(config, JSON.parse(rtfField.Data)) : EditorState.create(config), handleScrollToSelection: (editorView) => { const ref = editorView.domAtPos(editorView.state.selection.from); let refNode = ref.node as any; while (refNode && !("getBoundingClientRect" in refNode)) refNode = refNode.parentElement; - const r1 = refNode && refNode.getBoundingClientRect(); + const r1 = refNode?.getBoundingClientRect(); const r3 = self._ref.current!.getBoundingClientRect(); if (r1.top < r3.top || r1.top > r3.bottom) { r1 && (self._scrollRef.current!.scrollTop += (r1.top - r3.top) * self.props.ScreenToLocalTransform().Scale); @@ -767,6 +757,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & dispatchTransaction: this.dispatchTransaction, nodeViews: { dashComment(node, view, getPos) { return new DashDocCommentView(node, view, getPos); }, + dashField(node, view, getPos) { return new DashFieldView(node, view, getPos, self); }, dashDoc(node, view, getPos) { return new DashDocView(node, view, getPos, self); }, image(node, view, getPos) { return new ImageResizeView(node, view, getPos, self.props.addDocTab); }, summary(node, view, getPos) { return new SummaryView(node, view, getPos); }, @@ -777,9 +768,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & handlePaste: this.handlePaste, }); this._editorView.state.schema.Document = this.props.Document; - if (startup && this._editorView) { - Doc.GetProto(doc).documentText = undefined; - this._editorView.dispatch(this._editorView.state.tr.insertText(startup)); + const startupText = !rtfField && this._editorView && Field.toString(this.dataDoc[fieldKey] as Field); + if (startupText) { + this._editorView.dispatch(this._editorView.state.tr.insertText(startupText)); } } @@ -788,8 +779,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & FormattedTextBox.SelectOnLoad = ""; this.props.select(false); } - const rtf = doc ? Cast(doc[fieldKey], RichTextField) : undefined; - (selectOnLoad || (rtf && !rtf.Text)) && this._editorView!.focus(); + (selectOnLoad /* || !rtfField?.Text*/) && this._editorView!.focus(); // add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet. this._editorView!.state.storedMarks = [...(this._editorView!.state.storedMarks ? this._editorView!.state.storedMarks : []), schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.round(Date.now() / 1000 / 5) })]; } diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 499cd2877..7aad6f90e 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -210,7 +210,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> { inferType = async (data: FieldResult, metaKey: string) => { const options = { _width: 300, _height: 300, title: metaKey }; if (data instanceof RichTextField || typeof data === "string" || typeof data === "number") { - return Docs.Create.TextDocument(options); + return Docs.Create.TextDocument("", options); } else if (data instanceof List) { if (data.length === 0) { return Docs.Create.StackingDocument([], options); diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 1445b5b08..a48dc286e 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -83,13 +83,12 @@ export class WebBox extends DocAnnotatableComponent<FieldViewProps, WebDocument> const field = Cast(this.props.Document[this.props.fieldKey], WebField); if (field) url = field.url.href; - const newBox = Docs.Create.TextDocument({ + const newBox = Docs.Create.TextDocument(url, { x: NumCast(this.props.Document.x), y: NumCast(this.props.Document.y), title: url, _width: 200, _height: 70, - documentText: "@@@" + url }); SelectionManager.SelectedDocuments().map(dv => { diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index fe601175d..a9053fd55 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -558,7 +558,7 @@ export class PDFViewer extends DocAnnotatableComponent<IViewerProps, PdfDocument startDrag = (e: PointerEvent, ele: HTMLElement): void => { e.preventDefault(); e.stopPropagation(); - const targetDoc = Docs.Create.TextDocument({ _width: 200, _height: 200, title: "Note linked to " + this.props.Document.title }); + const targetDoc = Docs.Create.TextDocument("", { _width: 200, _height: 200, title: "Note linked to " + this.props.Document.title }); const annotationDoc = this.highlight("rgba(146, 245, 95, 0.467)"); // yellowish highlight color when dragging out a text selection if (annotationDoc) { DragManager.StartPdfAnnoDrag([ele], new DragManager.PdfAnnoDragData(this.props.Document, annotationDoc, targetDoc), e.pageX, e.pageY, { diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 818a30e9f..6f99af8f6 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -33,11 +33,11 @@ export class CurrentUserUtils { // a default set of note types .. not being used yet... static setupNoteTypes(doc: Doc) { return [ - Docs.Create.TextDocument({ title: "Note", backgroundColor: "yellow", isTemplateDoc: true }), - Docs.Create.TextDocument({ title: "Idea", backgroundColor: "pink", isTemplateDoc: true }), - Docs.Create.TextDocument({ title: "Topic", backgroundColor: "lightBlue", isTemplateDoc: true }), - Docs.Create.TextDocument({ title: "Person", backgroundColor: "lightGreen", isTemplateDoc: true }), - Docs.Create.TextDocument({ title: "Todo", backgroundColor: "orange", isTemplateDoc: true }) + Docs.Create.TextDocument("", { title: "Note", backgroundColor: "yellow", isTemplateDoc: true }), + Docs.Create.TextDocument("", { title: "Idea", backgroundColor: "pink", isTemplateDoc: true }), + Docs.Create.TextDocument("", { title: "Topic", backgroundColor: "lightBlue", isTemplateDoc: true }), + Docs.Create.TextDocument("", { title: "Person", backgroundColor: "lightGreen", isTemplateDoc: true }), + Docs.Create.TextDocument("", { title: "Todo", backgroundColor: "orange", isTemplateDoc: true }) ]; } |