From 710dda13398c01b2b0f63b033ccca0c8ea4f7e49 Mon Sep 17 00:00:00 2001
From: bob <bcz@cs.brown.edu>
Date: Wed, 4 Dec 2019 14:28:24 -0500
Subject: fixed mainview flyoutbehavior a bit.  fixed keyvaluebox editing of
 lists a little.

---
 src/client/views/nodes/KeyValueBox.tsx | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

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

diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index fba29e4cd..322d639dc 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -66,10 +66,10 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
         return { script, type: dubEq, onDelegate: eq };
     }
 
-    public static ApplyKVPScript(doc: Doc, key: string, kvpScript: KVPScript): boolean {
+    public static ApplyKVPScript(doc: Doc, key: string, kvpScript: KVPScript, forceOnDelegate?: boolean): boolean {
         const { script, type, onDelegate } = kvpScript;
         //const target = onDelegate ? Doc.Layout(doc.layout) : Doc.GetProto(doc); // bcz: TODO need to be able to set fields on layout templates
-        const target = onDelegate ? doc : Doc.GetProto(doc);
+        const target = forceOnDelegate || onDelegate ? doc : Doc.GetProto(doc);
         let field: Field;
         if (type === "computed") {
             field = new ComputedField(script);
@@ -88,10 +88,10 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
     }
 
     @undoBatch
-    public static SetField(doc: Doc, key: string, value: string) {
+    public static SetField(doc: Doc, key: string, value: string, forceOnDelegate?: boolean) {
         const script = this.CompileKVPScript(value);
         if (!script) return false;
-        return this.ApplyKVPScript(doc, key, script);
+        return this.ApplyKVPScript(doc, key, script, forceOnDelegate);
     }
 
     onPointerDown = (e: React.PointerEvent): void => {
-- 
cgit v1.2.3-70-g09d2


From 877a6f481a06e2454ff9d8eabe43acb0e58a2676 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 15 Dec 2019 10:38:23 -0500
Subject: writing selectedDocs to user doc to allow selection to be part of
 scripting

---
 src/client/util/DragManager.ts              |  2 +-
 src/client/util/SelectionManager.ts         |  3 +++
 src/client/views/nodes/FormattedTextBox.tsx |  2 +-
 src/client/views/nodes/KeyValueBox.tsx      |  3 ++-
 src/new_fields/Doc.ts                       | 12 +++++++++---
 5 files changed, 16 insertions(+), 6 deletions(-)

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

diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 2631a1e3c..df2f5fe3c 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -51,7 +51,7 @@ export function SetupDrag(
             e.stopPropagation();
             if (e.shiftKey && CollectionDockingView.Instance) {
                 e.persist();
-                let dragDoc = await docFunc();
+                const dragDoc = await docFunc();
                 dragDoc && CollectionDockingView.Instance.StartOtherDrag({
                     pageX: e.pageX,
                     pageY: e.pageY,
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index e01216e0f..d9283de35 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -2,6 +2,8 @@ import { observable, action, runInAction, ObservableMap } from "mobx";
 import { Doc } from "../../new_fields/Doc";
 import { DocumentView } from "../views/nodes/DocumentView";
 import { computedFn } from "mobx-utils";
+import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils";
+import { List } from "../../new_fields/List";
 
 export namespace SelectionManager {
 
@@ -27,6 +29,7 @@ export namespace SelectionManager {
                 manager.SelectedDocuments.clear();
                 manager.SelectedDocuments.set(docView, true);
             }
+            Doc.UserDoc().SelectedDocs = new List(SelectionManager.SelectedDocuments().map(dv => dv.props.Document));
         }
         @action
         DeselectDoc(docView: DocumentView): void {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index e40c00e54..3efbd434e 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -822,7 +822,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
                 clipboardTextSerializer: this.clipboardTextSerializer,
                 handlePaste: this.handlePaste,
             });
-            (this._editorView.state.schema as any).Document = this.props.Document;
+            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));
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 322d639dc..07d6d6f5e 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -57,7 +57,8 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
         value = eq ? value.substr(1) : value;
         const dubEq = value.startsWith(":=") ? "computed" : value.startsWith(";=") ? "script" : false;
         value = dubEq ? value.substr(2) : value;
-        const options: ScriptOptions = { addReturn: true, params: { this: "Doc" } };
+        const editable = value.includes("selectedDocs"); // bcz: Argh TODO - need a UI mechanism for letting user know that a function can't be run read-only. e.g., selectedDocs() wants to cache its old value so it can't be run read-only
+        const options: ScriptOptions = { addReturn: true, params: { this: "Doc" }, editable: editable };
         if (dubEq) options.typecheck = false;
         const script = CompileScript(value, options);
         if (!script.compiled) {
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index aa33d4c8b..a22b289bb 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -1,4 +1,4 @@
-import { observable, ObservableMap, runInAction, action } from "mobx";
+import { observable, ObservableMap, runInAction, action, untracked } from "mobx";
 import { alias, map, serializable } from "serializr";
 import { DocServer } from "../client/DocServer";
 import { DocumentType } from "../client/documents/DocumentTypes";
@@ -474,7 +474,7 @@ export namespace Doc {
         return extension ? extension as Doc : undefined;
     }
     export function fieldExtensionDocSync(doc: Doc, fieldKey: string) {
-        return (doc[fieldKey + "_ext"] as Doc) ||  CreateDocumentExtensionForField(doc, fieldKey);
+        return (doc[fieldKey + "_ext"] as Doc) || CreateDocumentExtensionForField(doc, fieldKey);
     }
 
     export function CreateDocumentExtensionForField(doc: Doc, fieldKey: string) {
@@ -753,4 +753,10 @@ Scripting.addGlobal(function aliasDocs(field: any) { return new List<Doc>(field.
 Scripting.addGlobal(function docList(field: any) { return DocListCast(field); });
 Scripting.addGlobal(function sameDocs(doc1: any, doc2: any) { return Doc.AreProtosEqual(doc1, doc2); });
 Scripting.addGlobal(function undo() { return UndoManager.Undo(); });
-Scripting.addGlobal(function redo() { return UndoManager.Redo(); });
\ No newline at end of file
+Scripting.addGlobal(function redo() { return UndoManager.Redo(); });
+Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: boolean) {
+    let docs = DocListCast(Doc.UserDoc().SelectedDocs).filter(d => (!excludeCollections || !Cast(d.data, listSpec(Doc), null)) && d.type !== DocumentType.KVP && !Doc.AreProtosEqual(d, container));
+    if (docs.length) untracked(() => container && (container.cachedSelection = new List(docs)));
+    else docs = untracked(() => DocListCast(container.cachedSelection));
+    return new List(docs);
+});
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 6683517a69f4806d026e7af85069f18b1f0a9d1f Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 15 Dec 2019 12:44:20 -0500
Subject: added _last_ for computedScripts to access last value of script

---
 src/client/util/RichTextSchema.tsx     | 6 +++++-
 src/client/views/nodes/KeyValueBox.tsx | 3 +--
 src/new_fields/Doc.ts                  | 5 ++---
 src/new_fields/ScriptField.ts          | 3 ++-
 4 files changed, 10 insertions(+), 7 deletions(-)

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

diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index 543f45731..7a048ed0d 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -741,7 +741,11 @@ export class DashDocView {
                 self._dashDoc = dashDoc;
                 dashDoc.hideSidebar = true;
                 if (node.attrs.width !== dashDoc.width + "px" || node.attrs.height !== dashDoc.height + "px") {
-                    view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, { ...node.attrs, width: dashDoc.width + "px", height: dashDoc.height + "px" }));
+                    try { // bcz: an exception will be thrown if two aliases are open at the same time when a doc view comment is made
+                        view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, { ...node.attrs, width: dashDoc.width + "px", height: dashDoc.height + "px" }));
+                    } catch (e) {
+                        console.log(e);
+                    }
                 }
                 this._reactionDisposer && this._reactionDisposer();
                 this._reactionDisposer = reaction(() => dashDoc[HeightSym]() + dashDoc[WidthSym](), () => {
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 07d6d6f5e..234a6a9d3 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -57,8 +57,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
         value = eq ? value.substr(1) : value;
         const dubEq = value.startsWith(":=") ? "computed" : value.startsWith(";=") ? "script" : false;
         value = dubEq ? value.substr(2) : value;
-        const editable = value.includes("selectedDocs"); // bcz: Argh TODO - need a UI mechanism for letting user know that a function can't be run read-only. e.g., selectedDocs() wants to cache its old value so it can't be run read-only
-        const options: ScriptOptions = { addReturn: true, params: { this: "Doc" }, editable: editable };
+        const options: ScriptOptions = { addReturn: true, params: { this: "Doc", _last_: "any" }, editable: false };
         if (dubEq) options.typecheck = false;
         const script = CompileScript(value, options);
         if (!script.compiled) {
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index a22b289bb..171f3fd2d 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -754,9 +754,8 @@ Scripting.addGlobal(function docList(field: any) { return DocListCast(field); })
 Scripting.addGlobal(function sameDocs(doc1: any, doc2: any) { return Doc.AreProtosEqual(doc1, doc2); });
 Scripting.addGlobal(function undo() { return UndoManager.Undo(); });
 Scripting.addGlobal(function redo() { return UndoManager.Redo(); });
-Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: boolean) {
+Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: boolean, prevValue: any) {
     let docs = DocListCast(Doc.UserDoc().SelectedDocs).filter(d => (!excludeCollections || !Cast(d.data, listSpec(Doc), null)) && d.type !== DocumentType.KVP && !Doc.AreProtosEqual(d, container));
-    if (docs.length) untracked(() => container && (container.cachedSelection = new List(docs)));
-    else docs = untracked(() => DocListCast(container.cachedSelection));
+    if (!docs.length) return prevValue;
     return new List(docs);
 });
\ No newline at end of file
diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts
index 6b2723663..0cadb60ed 100644
--- a/src/new_fields/ScriptField.ts
+++ b/src/new_fields/ScriptField.ts
@@ -124,8 +124,9 @@ export class ScriptField extends ObjectField {
 @scriptingGlobal
 @Deserializable("computed", deserializeScript)
 export class ComputedField extends ScriptField {
+    _lastComputedResult: any;
     //TODO maybe add an observable cache based on what is passed in for doc, considering there shouldn't really be that many possible values for doc
-    value = computedFn((doc: Doc) => this.script.run({ this: doc }, console.log).result);
+    value = computedFn((doc: Doc) => this._lastComputedResult = this.script.run({ this: doc, _last_: this._lastComputedResult }, console.log).result);
     public static MakeScript(script: string, params: object = {}, ) {
         const compiled = ScriptField.CompileScript(script, params, false);
         return compiled.compiled ? new ComputedField(compiled) : undefined;
-- 
cgit v1.2.3-70-g09d2

