From e3709b4445732791f696cdf26274ab09294ce208 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sat, 27 Jan 2024 04:21:08 -0500
Subject: made dataViz nodes linked to schema nodes update automatically as
 cahnges are made.  fixed user created templates from disappearing from menu,
 and made them work.  added toJavascriptString and made DashField views
 convert to text.  added support for turning text into javascript rendering
 (paint) code.

---
 .../views/nodes/formattedText/FormattedTextBox.tsx | 34 ++++++++++++++++++----
 1 file changed, 29 insertions(+), 5 deletions(-)

(limited to 'src/client/views/nodes/formattedText/FormattedTextBox.tsx')

diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 731ab1d53..6f9c2893e 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -67,6 +67,7 @@ import { RichTextMenu, RichTextMenuPlugin } from './RichTextMenu';
 import { RichTextRules } from './RichTextRules';
 import { schema } from './schema_rts';
 import { SummaryView } from './SummaryView';
+import { CollectionView } from '../../collections/CollectionView';
 // import * as applyDevTools from 'prosemirror-dev-tools';
 @observer
 export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps>() implements ViewBoxInterface {
@@ -325,13 +326,26 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
         } catch (e) {}
     };
 
+    leafText = (node: Node) => {
+        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);
+            return Field.toJavascriptString(refDoc[node.attrs.fieldKey as string] as Field);
+        }
+        return '';
+    };
     dispatchTransaction = (tx: Transaction) => {
         if (this._editorView && (this._editorView as any).docView) {
             const state = this._editorView.state.apply(tx);
             this._editorView.updateState(state);
+            this.tryUpdateDoc(false);
+        }
+    };
 
+    tryUpdateDoc = (force: boolean) => {
+        if (this._editorView && (this._editorView as any).docView) {
+            const state = this._editorView.state;
             const dataDoc = Doc.IsDelegateField(DocCast(this.layoutDoc.proto), this.fieldKey) ? DocCast(this.layoutDoc.proto) : this.dataDoc;
-            const newText = state.doc.textBetween(0, state.doc.content.size, ' \n');
+            const newText = state.doc.textBetween(0, state.doc.content.size, ' \n', this.leafText);
             const newJson = JSON.stringify(state.toJSON());
             const prevData = Cast(this.layoutDoc[this.fieldKey], RichTextField, null); // the actual text in the text box
             const templateData = this.Document !== this.layoutDoc ? prevData : undefined; // the default text stored in a layout template
@@ -350,13 +364,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
                 dataDoc.tags = accumTags.length ? new List<string>(Array.from(new Set<string>(accumTags))) : undefined;
 
                 let unchanged = true;
-                if (this._applyingChange !== this.fieldKey && removeSelection(newJson) !== removeSelection(prevData?.Data)) {
+                if (this._applyingChange !== this.fieldKey && (force || removeSelection(newJson) !== removeSelection(prevData?.Data))) {
                     this._applyingChange = this.fieldKey;
                     const textChange = newText !== prevData?.Text;
                     textChange && (dataDoc[this.fieldKey + '_modificationDate'] = new DateField(new Date(Date.now())));
                     if ((!prevData && !protoData) || newText || (!newText && !templateData)) {
                         // if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended)
-                        if ((this._finishingLink || this._props.isContentActive() || this._inDrop) && removeSelection(newJson) !== removeSelection(prevData?.Data)) {
+                        if (force || ((this._finishingLink || this._props.isContentActive() || this._inDrop) && removeSelection(newJson) !== removeSelection(prevData?.Data))) {
                             const numstring = NumCast(dataDoc[this.fieldKey], null);
                             dataDoc[this.fieldKey] = numstring !== undefined ? Number(newText) : new RichTextField(newJson, newText);
                             dataDoc[this.fieldKey + '_noTemplate'] = true; // mark the data field as being split from the template if it has been edited
@@ -480,7 +494,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
             var alink: Doc | undefined;
             this.findInNode(editorView, editorView.state.doc, autoLinkTerm).forEach(sel => {
                 const splitter = editorView.state.schema.marks.splitter.create({ id: Utils.GenerateGuid() });
-                if (!sel.$anchor.pos || editorView.state.doc.textBetween(sel.$anchor.pos - 1, sel.$to.pos).trim() === autoLinkTerm) {
+                if (!sel.$anchor.pos || [autoLinkTerm, StrCast(target.title)].includes(editorView.state.doc.textBetween(sel.$anchor.pos - 1, sel.$to.pos).trim())) {
                     tr = tr.addMark(sel.from, sel.to, splitter);
                     tr.doc.nodesBetween(sel.from, sel.to, (node: any, pos: number, parent: any) => {
                         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)) {
@@ -919,6 +933,17 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
                 event: () => (this.layoutDoc._createDocOnCR = !this.layoutDoc._createDocOnCR),
                 icon: !this.Document._createDocOnCR ? 'grip-lines' : 'bars',
             });
+        optionItems.push({
+            description: 'Make Paint Function',
+            event: () => {
+                this.dataDoc.layout_painted = CollectionView.LayoutString('painted');
+                this.layoutDoc.layout_fieldKey = 'layout_painted';
+                this.layoutDoc.type_collection = CollectionViewType.Freeform;
+                this.DocumentView?.().setToggleDetail();
+                this.dataDoc.paintFunc = ComputedField.MakeFunction(`toJavascriptString(this['${this.fieldKey}']?.Text)`);
+            },
+            icon: !this.Document._layout_enableAltContentUI ? 'eye-slash' : 'eye',
+        });
         !Doc.noviceMode &&
             optionItems.push({
                 description: `${this.Document._layout_autoHeight ? 'Lock' : 'Auto'} Height`,
@@ -1682,7 +1707,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
         FormattedTextBox.LiveTextUndo = undefined;
 
         const state = this._editorView!.state;
-        const curText = state.doc.textBetween(0, state.doc.content.size, ' \n');
         if (StrCast(this.Document.title).startsWith('@') && !this.dataDoc.title_custom) {
             UndoManager.RunInBatch(() => {
                 this.dataDoc.title_custom = true;
-- 
cgit v1.2.3-70-g09d2

