From 5ec467d2c03f98a6070361caf5727dece6327c29 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 7 Jul 2022 14:57:23 -0400 Subject: got rid of typings for ReactTextareaAutocomplete to avoid react warnings. --- src/client/views/nodes/ScriptingBox.tsx | 761 +++++++++++++++++++------------- 1 file changed, 446 insertions(+), 315 deletions(-) (limited to 'src/client/views/nodes/ScriptingBox.tsx') diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx index 366c3fc2f..05ff40f22 100644 --- a/src/client/views/nodes/ScriptingBox.tsx +++ b/src/client/views/nodes/ScriptingBox.tsx @@ -1,39 +1,39 @@ -import ReactTextareaAutocomplete from "@webscopeio/react-textarea-autocomplete"; -import "@webscopeio/react-textarea-autocomplete/style.css"; -import { action, computed, observable } from "mobx"; -import { observer } from "mobx-react"; -import * as React from "react"; -import { Doc } from "../../../fields/Doc"; -import { List } from "../../../fields/List"; -import { listSpec } from "../../../fields/Schema"; -import { ScriptField } from "../../../fields/ScriptField"; -import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types"; -import { TraceMobx } from "../../../fields/util"; -import { returnEmptyString } from "../../../Utils"; -import { DragManager } from "../../util/DragManager"; -import { InteractionUtils } from "../../util/InteractionUtils"; -import { CompileScript, ScriptParam } from "../../util/Scripting"; -import { ScriptingGlobals } from "../../util/ScriptingGlobals"; -import { ScriptManager } from "../../util/ScriptManager"; -import { ContextMenu } from "../ContextMenu"; -import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from "../DocComponent"; -import { EditableView } from "../EditableView"; -import { FieldView, FieldViewProps } from "../nodes/FieldView"; -import { OverlayView } from "../OverlayView"; -import { DocumentIconContainer } from "./DocumentIcon"; -import "./ScriptingBox.scss"; -const _global = (window /* browser */ || global /* node */) as any; +let ReactTextareaAutocomplete = require('@webscopeio/react-textarea-autocomplete').default; +import { action, computed, observable } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { Doc } from '../../../fields/Doc'; +import { List } from '../../../fields/List'; +import { listSpec } from '../../../fields/Schema'; +import { ScriptField } from '../../../fields/ScriptField'; +import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; +import { TraceMobx } from '../../../fields/util'; +import { returnEmptyString } from '../../../Utils'; +import { DragManager } from '../../util/DragManager'; +import { InteractionUtils } from '../../util/InteractionUtils'; +import { CompileScript, ScriptParam } from '../../util/Scripting'; +import { ScriptingGlobals } from '../../util/ScriptingGlobals'; +import { ScriptManager } from '../../util/ScriptManager'; +import { ContextMenu } from '../ContextMenu'; +import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent'; +import { EditableView } from '../EditableView'; +import { FieldView, FieldViewProps } from '../nodes/FieldView'; +import { OverlayView } from '../OverlayView'; +import { DocumentIconContainer } from './DocumentIcon'; +import './ScriptingBox.scss'; +const _global = (window /* browser */ || global) /* node */ as any; @observer export class ScriptingBox extends ViewBoxAnnotatableComponent() { - private dropDisposer?: DragManager.DragDropDisposer; protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer | undefined; - public static LayoutString(fieldStr: string) { return FieldView.LayoutString(ScriptingBox, fieldStr); } + public static LayoutString(fieldStr: string) { + return FieldView.LayoutString(ScriptingBox, fieldStr); + } private _overlayDisposer?: () => void; private _caretPos = 0; - @observable private _errorMessage: string = ""; + @observable private _errorMessage: string = ''; @observable private _applied: boolean = false; @observable private _function: boolean = false; @observable private _spaced: boolean = false; @@ -42,12 +42,12 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent p.split(":")[0].trim()); } - @computed({ keepAlive: true }) get paramsTypes() { return this.compileParams.map(p => p.split(":")[1].trim()); } - @computed({ keepAlive: true }) get rawScript() { return StrCast(this.dataDoc[this.props.fieldKey + "-rawScript"], ""); } - @computed({ keepAlive: true }) get functionName() { return StrCast(this.dataDoc[this.props.fieldKey + "-functionName"], ""); } - @computed({ keepAlive: true }) get functionDescription() { return StrCast(this.dataDoc[this.props.fieldKey + "-functionDescription"], ""); } - @computed({ keepAlive: true }) get compileParams() { return Cast(this.dataDoc[this.props.fieldKey + "-params"], listSpec("string"), []); } + @computed({ keepAlive: true }) get paramsNames() { + return this.compileParams.map(p => p.split(':')[0].trim()); + } + @computed({ keepAlive: true }) get paramsTypes() { + return this.compileParams.map(p => p.split(':')[1].trim()); + } + @computed({ keepAlive: true }) get rawScript() { + return StrCast(this.dataDoc[this.props.fieldKey + '-rawScript'], ''); + } + @computed({ keepAlive: true }) get functionName() { + return StrCast(this.dataDoc[this.props.fieldKey + '-functionName'], ''); + } + @computed({ keepAlive: true }) get functionDescription() { + return StrCast(this.dataDoc[this.props.fieldKey + '-functionDescription'], ''); + } + @computed({ keepAlive: true }) get compileParams() { + return Cast(this.dataDoc[this.props.fieldKey + '-params'], listSpec('string'), []); + } - set rawScript(value) { this.dataDoc[this.props.fieldKey + "-rawScript"] = value; } - set functionName(value) { this.dataDoc[this.props.fieldKey + "-functionName"] = value; } - set functionDescription(value) { this.dataDoc[this.props.fieldKey + "-functionDescription"] = value; } + set rawScript(value) { + this.dataDoc[this.props.fieldKey + '-rawScript'] = value; + } + set functionName(value) { + this.dataDoc[this.props.fieldKey + '-functionName'] = value; + } + set functionDescription(value) { + this.dataDoc[this.props.fieldKey + '-functionDescription'] = value; + } - set compileParams(value) { this.dataDoc[this.props.fieldKey + "-params"] = new List(value); } + set compileParams(value) { + this.dataDoc[this.props.fieldKey + '-params'] = new List(value); + } getValue(result: any, descrip: boolean) { - if (typeof result === "object") { + if (typeof result === 'object') { const text = descrip ? result[1] : result[2]; - return text !== undefined ? text : ""; + return text !== undefined ? text : ''; } else { - return ""; + return ''; } } @@ -89,17 +109,19 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent { - const area = document.querySelector('textarea'); - if (area) { - for (const { } of entries) { - const getCaretCoordinates = require('textarea-caret'); - const caret = getCaretCoordinates(area, this._selection); - this.resetSuggestionPos(caret); + const observer = new _global.ResizeObserver( + action((entries: any) => { + const area = document.querySelector('textarea'); + if (area) { + for (const {} of entries) { + const getCaretCoordinates = require('textarea-caret'); + const caret = getCaretCoordinates(area, this._selection); + this.resetSuggestionPos(caret); + } } - } - })); - observer.observe(document.getElementsByClassName("scriptingBox")[0]); + }) + ); + observer.observe(document.getElementsByClassName('scriptingBox')[0]); } @action @@ -110,8 +132,8 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent (x + scriptWidth)) { - const diff = (left + suggestionWidth) - (x + scriptWidth); + if (left + suggestionWidth > x + scriptWidth) { + const diff = left + suggestionWidth - (x + scriptWidth); left = left - diff; } @@ -123,52 +145,53 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent void) => { //used for stacking and masonry view + protected createDashEventsTarget = (ele: HTMLDivElement, dropFunc: (e: Event, de: DragManager.DropEvent) => void) => { + //used for stacking and masonry view if (ele) { this.dropDisposer?.(); this.dropDisposer = DragManager.MakeDropTarget(ele, dropFunc, this.layoutDoc); } - } + }; // only included in buttons, transforms scripting UI to a button @action onFinish = () => { - this.rootDoc.layoutKey = "layout"; - } + this.rootDoc.layoutKey = 'layout'; + }; // displays error message @action onError = (error: any) => { - this._errorMessage = error?.message ? error.message : error?.map((entry: any) => entry.messageText).join(" ") || ""; - } + this._errorMessage = error?.message ? error.message : error?.map((entry: any) => entry.messageText).join(' ') || ''; + }; // checks if the script compiles using CompileScript method and inputting params @action onCompile = () => { const params: ScriptParam = {}; - this.compileParams.forEach(p => params[p.split(":")[0].trim()] = p.split(":")[1].trim()); + this.compileParams.forEach(p => (params[p.split(':')[0].trim()] = p.split(':')[1].trim())); const result = CompileScript(this.rawScript, { editable: true, transformer: DocumentIconContainer.getTransformer(), params, - typecheck: false + typecheck: false, }); this.dataDoc[this.fieldKey] = result.compiled ? new ScriptField(result) : undefined; this.onError(result.compiled ? undefined : result.errors); return result.compiled; - } + }; // checks if the script compiles and then runs the script @action onRun = () => { if (this.onCompile()) { const bindings: { [name: string]: any } = {}; - this.paramsNames.forEach(key => bindings[key] = this.dataDoc[key]); + this.paramsNames.forEach(key => (bindings[key] = this.dataDoc[key])); // binds vars so user doesnt have to refer to everything as self. ScriptCast(this.dataDoc[this.fieldKey], null)?.script.run({ self: this.rootDoc, this: this.layoutDoc, ...bindings }, this.onError); } - } + }; // checks if the script compiles and switches to applied UI @action @@ -176,39 +199,39 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent { - this._errorMessage = ""; + this._errorMessage = ''; this._applied = false; this._function = false; - } + }; @action onSave = () => { if (this.onCompile()) { this._function = true; } else { - this._errorMessage = "Can not save script, does not compile"; + this._errorMessage = 'Can not save script, does not compile'; } - } + }; @action onCreate = () => { - this._errorMessage = ""; + this._errorMessage = ''; if (this.functionName.length === 0) { - this._errorMessage = "Must enter a function name"; + this._errorMessage = 'Must enter a function name'; return false; } - if (this.functionName.indexOf(" ") > 0) { - this._errorMessage = "Name can not include spaces"; + if (this.functionName.indexOf(' ') > 0) { + this._errorMessage = 'Name can not include spaces'; return false; } - if (this.functionName.indexOf(".") > 0) { + if (this.functionName.indexOf('.') > 0) { this._errorMessage = "Name can not include '.'"; return false; } @@ -223,173 +246,184 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent { this._overlayDisposer?.(); this._overlayDisposer = OverlayView.Instance.addElement(, { x: 0, y: 0 }); - } + }; // sets field of the corresponding field key (param name) to be dropped document @action onDrop = (e: Event, de: DragManager.DropEvent, fieldKey: string) => { this.dataDoc[fieldKey] = de.complete.docDragData?.droppedDocuments[0]; e.stopPropagation(); - } + }; - // deletes a param from all areas in which it is stored + // deletes a param from all areas in which it is stored @action onDelete = (num: number) => { this.dataDoc[this.paramsNames[num]] = undefined; this.compileParams.splice(num, 1); return true; - } + }; // sets field of the param name to the selected value in drop down box @action viewChanged = (e: React.ChangeEvent, name: string) => { //@ts-ignore const val = e.target.selectedOptions[0].value; - this.dataDoc[name] = val[0] === "S" ? val.substring(1) : val[0] === "N" ? parseInt(val.substring(1)) : val.substring(1) === "true"; - } + this.dataDoc[name] = val[0] === 'S' ? val.substring(1) : val[0] === 'N' ? parseInt(val.substring(1)) : val.substring(1) === 'true'; + }; // creates a copy of the script document onCopy = () => { const copy = Doc.MakeCopy(this.rootDoc, true); copy.x = NumCast(this.dataDoc.x) + NumCast(this.dataDoc._width); this.props.addDocument?.(copy); - } + }; // adds option to create a copy to the context menu specificContextMenu = (): void => { - const existingOptions = ContextMenu.Instance.findByDescription("Options..."); - const options = existingOptions && "subitems" in existingOptions ? existingOptions.subitems : []; - options.push({ description: "Create a Copy", event: this.onCopy, icon: "copy" }); - !existingOptions && ContextMenu.Instance.addItem({ description: "Options...", subitems: options, icon: "hand-point-right" }); - } + const existingOptions = ContextMenu.Instance.findByDescription('Options...'); + const options = existingOptions && 'subitems' in existingOptions ? existingOptions.subitems : []; + options.push({ description: 'Create a Copy', event: this.onCopy, icon: 'copy' }); + !existingOptions && ContextMenu.Instance.addItem({ description: 'Options...', subitems: options, icon: 'hand-point-right' }); + }; renderFunctionInputs() { - const descriptionInput = - -
{params}
+
{params}
- - + +
); @@ -90,35 +94,43 @@ export class ScriptBox extends React.Component { // tslint:disable-next-line: no-unnecessary-callback-wrapper const params: string[] = []; const setParams = (p: string[]) => params.splice(0, params.length, ...p); - const scriptingBox = { - if (!text) { - Doc.GetProto(doc)[fieldKey] = undefined; - } else { - const script = CompileScript(text, { - params: { this: Doc.name, ...contextParams }, - typecheck: false, - editable: true, - transformer: DocumentIconContainer.getTransformer() - }); - if (!script.compiled) { - onError(script.errors.map(error => error.messageText).join("\n")); - return; - } + const scriptingBox = ( + { + if (!text) { + Doc.GetProto(doc)[fieldKey] = undefined; + } else { + const script = CompileScript(text, { + params: { this: Doc.name, ...contextParams }, + typecheck: false, + editable: true, + transformer: DocumentIconContainer.getTransformer(), + }); + if (!script.compiled) { + onError(script.errors.map(error => error.messageText).join('\n')); + return; + } - const div = document.createElement("div"); - div.style.width = "90"; - div.style.height = "20"; - div.style.background = "gray"; - div.style.position = "absolute"; - div.style.display = "inline-block"; - div.style.transform = `translate(${clientX}px, ${clientY}px)`; - div.innerHTML = "button"; - params.length && DragManager.StartButtonDrag([div], text, doc.title + "-instance", {}, params, (button: Doc) => { }, clientX, clientY); + const div = document.createElement('div'); + div.style.width = '90'; + div.style.height = '20'; + div.style.background = 'gray'; + div.style.position = 'absolute'; + div.style.display = 'inline-block'; + div.style.transform = `translate(${clientX}px, ${clientY}px)`; + div.innerHTML = 'button'; + params.length && DragManager.StartButtonDrag([div], text, doc.title + '-instance', {}, params, (button: Doc) => {}, clientX, clientY); - Doc.GetProto(doc)[fieldKey] = new ScriptField(script); - overlayDisposer(); - } - }} showDocumentIcons />; + Doc.GetProto(doc)[fieldKey] = new ScriptField(script); + overlayDisposer(); + } + }} + showDocumentIcons + /> + ); overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, { x: 400, y: 200, width: 500, height: 400, title }); } } diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 156513f47..863829a51 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -55,16 +55,12 @@ export class TemplateMenu extends React.Component { @observable private _hidden: boolean = true; toggleLayout = (e: React.ChangeEvent, layout: string): void => { - this.props.docViews.map(dv => dv.switchViews(e.target.checked, layout)); + this.props.docViews.map(dv => dv.switchViews(e.target.checked, layout, undefined, true)); }; toggleDefault = (e: React.ChangeEvent): void => { this.props.docViews.map(dv => dv.switchViews(false, 'layout')); }; - toggleAudio = (e: React.ChangeEvent): void => { - this.props.docViews.map(dv => (dv.props.Document._showAudio = e.target.checked)); - }; - @undoBatch @action toggleTemplate = (event: React.ChangeEvent, template: string): void => { @@ -76,12 +72,6 @@ export class TemplateMenu extends React.Component { this._hidden = !this._hidden; }; - @undoBatch - @action - toggleChrome = (): void => { - this.props.docViews.map(dv => Doc.Layout(dv.layoutDoc)).forEach(layout => (layout._chromeHidden = !layout._chromeHidden)); - }; - // todo: add brushes to brushMap to save with a style name onCustomKeypress = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { @@ -95,13 +85,9 @@ export class TemplateMenu extends React.Component { .map(key => runInAction(() => this._addedKeys.add(key.replace('layout_', '')))); } - return100 = () => 100; + return100 = () => 300; @computed get scriptField() { - const script = ScriptField.MakeScript( - 'docs.map(d => switchView(d, this))', - { this: Doc.name, heading: 'string', checked: 'string', containingTreeView: Doc.name, firstDoc: Doc.name }, - { docs: new List(this.props.docViews.map(dv => dv.props.Document)) } - ); + const script = ScriptField.MakeScript('docs.map(d => switchView(d, this))', { this: Doc.name }, { docs: this.props.docViews.map(dv => dv.props.Document) as any }); return script ? () => script : undefined; } templateIsUsed = (selDoc: Doc, templateDoc: Doc) => { @@ -113,13 +99,10 @@ export class TemplateMenu extends React.Component { const firstDoc = this.props.docViews[0].props.Document; const templateName = StrCast(firstDoc.layoutKey, 'layout').replace('layout_', ''); const noteTypes = DocListCast(Cast(Doc.UserDoc()['template-notes'], Doc, null)?.data); - const addedTypes = Doc.noviceMode ? [] : DocListCast(Cast(Doc.UserDoc()['template-buttons'], Doc, null)?.data); - const layout = Doc.Layout(firstDoc); + const addedTypes = DocListCast(Cast(Doc.UserDoc()['template-clickFuncs'], Doc, null)?.data); const templateMenu: Array = []; this.props.templates?.forEach((checked, template) => templateMenu.push()); - templateMenu.push(); templateMenu.push(); - !Doc.noviceMode && templateMenu.push(); addedTypes.concat(noteTypes).map(template => (template.treeViewChecked = this.templateIsUsed(firstDoc, template))); this._addedKeys && Array.from(this._addedKeys) @@ -129,43 +112,42 @@ export class TemplateMenu extends React.Component {
    {Doc.noviceMode ? null : } {templateMenu} - {Doc.noviceMode ? null : ( - - )} +
); } diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 6850fb23a..a6c367ff7 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -296,7 +296,7 @@ export class CollectionStackingView extends CollectionSubView.documentView-node { + > .documentView-node { position: absolute; } } @@ -158,7 +158,7 @@ top: 0; width: 100%; height: 14; - background: rgba(0, 0, 0, .4); + background: rgba(0, 0, 0, 0.4); text-align: center; text-overflow: ellipsis; white-space: pre; @@ -187,19 +187,18 @@ transition: opacity 0.5s; } } - } .documentView-node:hover, .documentView-node-topmost:hover { - >.documentView-styleWrapper { - >.documentView-titleWrapper-hover { + > .documentView-styleWrapper { + > .documentView-titleWrapper-hover { display: inline-block; } } - >.documentView-styleWrapper { - >.documentView-captionWrapper { + > .documentView-styleWrapper { + > .documentView-captionWrapper { opacity: 1; } } @@ -225,6 +224,6 @@ .documentView-node:first-child { position: relative; - background: "#B59B66"; //$white; + background: '#B59B66'; //$white; } -} \ No newline at end of file +} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 8847c0c6a..edaa40bad 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -177,6 +177,7 @@ export interface DocumentViewProps extends DocumentViewSharedProps { dontScaleFilter?: (doc: Doc) => boolean; // decides whether a document can be scaled to fit its container vs native size with scrolling NativeWidth?: () => number; NativeHeight?: () => number; + NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal NOTE: Must also be added to FieldViewProps LayoutTemplate?: () => Opt; contextMenuItems?: () => { script: ScriptField; filter?: ScriptField; label: string; icon: string }[]; onClick?: () => ScriptField; @@ -191,7 +192,6 @@ export interface DocumentViewProps extends DocumentViewSharedProps { export interface DocumentViewInternalProps extends DocumentViewProps { NativeWidth: () => number; NativeHeight: () => number; - NativeDimScaling?: () => number; // scaling the DocumentView does to transform its contents into its panel & needed by ScreenToLocal NOTE: Must also be added to FieldViewProps isSelected: (outsideReaction?: boolean) => boolean; select: (ctrlPressed: boolean) => void; DocumentView: () => DocumentView; @@ -716,7 +716,7 @@ export class DocumentViewInternal extends DocComponent this.props.removeDocument?.(this.props.Document); - @undoBatch setToggleDetail = () => (this.Document.onClick = ScriptField.MakeScript(`toggleDetail(documentView, "${StrCast(this.Document.layoutKey).replace('layout_', '')}")`, { documentView: 'any' })); + @undoBatch setToggleDetail = () => + (this.Document.onClick = ScriptField.MakeScript( + `toggleDetail(documentView, "${StrCast(this.Document.layoutKey) + .replace('layout_', '') + .replace(/^layout$/, 'detail')}")`, + { documentView: 'any' } + )); @undoBatch @action @@ -1538,11 +1544,15 @@ export class DocumentView extends React.Component { Doc.setNativeView(this.props.Document); custom && DocUtils.makeCustomViewClicked(this.props.Document, Docs.Create.StackingDocument, layout, undefined); }; - switchViews = action((custom: boolean, view: string, finished?: () => void) => { + switchViews = action((custom: boolean, view: string, finished?: () => void, useExistingLayout = false) => { this.docView && (this.docView._animateScalingTo = 0.1); // shrink doc setTimeout( action(() => { - this.setCustomView(custom, view); + if (useExistingLayout && custom && this.rootDoc['layout_' + view]) { + this.rootDoc.layoutKey = 'layout_' + view; + } else { + this.setCustomView(custom, view); + } this.docView && (this.docView._animateScalingTo = 1); // expand it setTimeout( action(() => { @@ -1646,7 +1656,7 @@ ScriptingGlobals.add(function deiconifyView(documentView: DocumentView) { ScriptingGlobals.add(function toggleDetail(dv: DocumentView, detailLayoutKeySuffix: string) { if (dv.Document.layoutKey === 'layout_' + detailLayoutKeySuffix) dv.switchViews(false, 'layout'); - else dv.switchViews(true, detailLayoutKeySuffix); + else dv.switchViews(true, detailLayoutKeySuffix, undefined, true); }); ScriptingGlobals.add(function updateLinkCollection(linkCollection: Doc) { diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 5a6c49809..dd2c13391 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -4,10 +4,9 @@ import { observer } from 'mobx-react'; import { DateField } from '../../../fields/DateField'; import { Doc, Field, FieldResult, Opt } from '../../../fields/Doc'; import { List } from '../../../fields/List'; -import { WebField } from '../../../fields/URLField'; -import { DocumentView, DocumentViewSharedProps } from './DocumentView'; import { ScriptField } from '../../../fields/ScriptField'; -import { RecordingBox } from './RecordingBox'; +import { WebField } from '../../../fields/URLField'; +import { DocumentViewSharedProps } from './DocumentView'; // // these properties get assigned through the render() method of the DocumentView when it creates this node. diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx index 05ff40f22..1c9b0bc0e 100644 --- a/src/client/views/nodes/ScriptingBox.tsx +++ b/src/client/views/nodes/ScriptingBox.tsx @@ -6,7 +6,7 @@ import { Doc } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; import { ScriptField } from '../../../fields/ScriptField'; -import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; +import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; import { returnEmptyString } from '../../../Utils'; import { DragManager } from '../../util/DragManager'; @@ -60,6 +60,14 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent !p.startsWith('_')) + .map(key => key + ':' + params[key]); + } + } } // vars included in fields that store parameters types and names and the script itself @@ -70,30 +78,30 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent p.split(':')[1].trim()); } @computed({ keepAlive: true }) get rawScript() { - return StrCast(this.dataDoc[this.props.fieldKey + '-rawScript'], ''); + return ScriptCast(this.rootDoc[this.fieldKey])?.script.originalScript ?? ''; } @computed({ keepAlive: true }) get functionName() { - return StrCast(this.dataDoc[this.props.fieldKey + '-functionName'], ''); + return StrCast(this.rootDoc[this.props.fieldKey + '-functionName'], ''); } @computed({ keepAlive: true }) get functionDescription() { - return StrCast(this.dataDoc[this.props.fieldKey + '-functionDescription'], ''); + return StrCast(this.rootDoc[this.props.fieldKey + '-functionDescription'], ''); } @computed({ keepAlive: true }) get compileParams() { - return Cast(this.dataDoc[this.props.fieldKey + '-params'], listSpec('string'), []); + return Cast(this.rootDoc[this.props.fieldKey + '-params'], listSpec('string'), []); } set rawScript(value) { - this.dataDoc[this.props.fieldKey + '-rawScript'] = value; + Doc.SetInPlace(this.rootDoc, this.props.fieldKey, new ScriptField(undefined, undefined, value), true); } set functionName(value) { - this.dataDoc[this.props.fieldKey + '-functionName'] = value; + Doc.SetInPlace(this.rootDoc, this.props.fieldKey + '-functionName', value, true); } set functionDescription(value) { - this.dataDoc[this.props.fieldKey + '-functionDescription'] = value; + Doc.SetInPlace(this.rootDoc, this.props.fieldKey + '-functionDescription', value, true); } set compileParams(value) { - this.dataDoc[this.props.fieldKey + '-params'] = new List(value); + Doc.SetInPlace(this.rootDoc, this.props.fieldKey + '-params', new List(value), true); } getValue(result: any, descrip: boolean) { @@ -107,8 +115,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent { const area = document.querySelector('textarea'); @@ -171,13 +178,13 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent (params[p.split(':')[0].trim()] = p.split(':')[1].trim())); - const result = CompileScript(this.rawScript, { + const result = CompileScript(this.rawText, { editable: true, transformer: DocumentIconContainer.getTransformer(), params, typecheck: false, }); - this.dataDoc[this.fieldKey] = result.compiled ? new ScriptField(result) : undefined; + Doc.SetInPlace(this.rootDoc, this.fieldKey, result.compiled ? new ScriptField(result, undefined, this.rawText) : new ScriptField(undefined, undefined, this.rawText), true); this.onError(result.compiled ? undefined : result.errors); return result.compiled; }; @@ -187,9 +194,9 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent { if (this.onCompile()) { const bindings: { [name: string]: any } = {}; - this.paramsNames.forEach(key => (bindings[key] = this.dataDoc[key])); + this.paramsNames.forEach(key => (bindings[key] = this.rootDoc[key])); // binds vars so user doesnt have to refer to everything as self. - ScriptCast(this.dataDoc[this.fieldKey], null)?.script.run({ self: this.rootDoc, this: this.layoutDoc, ...bindings }, this.onError); + ScriptCast(this.rootDoc[this.fieldKey], null)?.script.run({ self: this.rootDoc, this: this.layoutDoc, ...bindings }, this.onError); } }; @@ -257,14 +264,14 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent { - this.dataDoc[fieldKey] = de.complete.docDragData?.droppedDocuments[0]; + Doc.SetInPlace(this.rootDoc, fieldKey, de.complete.docDragData?.droppedDocuments[0], true); e.stopPropagation(); }; // deletes a param from all areas in which it is stored @action onDelete = (num: number) => { - this.dataDoc[this.paramsNames[num]] = undefined; + Doc.SetInPlace(this.rootDoc, this.paramsNames[num], undefined, true); this.compileParams.splice(num, 1); return true; }; @@ -274,7 +281,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent { //@ts-ignore const val = e.target.selectedOptions[0].value; - this.dataDoc[name] = val[0] === 'S' ? val.substring(1) : val[0] === 'N' ? parseInt(val.substring(1)) : val.substring(1) === 'true'; + Doc.SetInPlace(this.rootDoc, name, val[0] === 'S' ? val.substring(1) : val[0] === 'N' ? parseInt(val.substring(1)) : val.substring(1) === 'true', true); }; // creates a copy of the script document @@ -330,8 +337,8 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent this.dataDoc[parameter]?.title ?? 'undefined'} + contents={StrCast(DocCast(this.rootDoc[parameter])?.title, 'undefined')} + GetValue={() => StrCast(DocCast(this.rootDoc[parameter])?.title, 'undefined')} SetValue={action((value: string) => { const script = CompileScript(value, { addReturn: true, @@ -341,7 +348,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent e.stopPropagation()} onChange={e => this.viewChanged(e, parameter)} - value={typeof this.dataDoc[parameter] === 'string' ? 'S' + StrCast(this.dataDoc[parameter]) : typeof this.dataDoc[parameter] === 'number' ? 'N' + NumCast(this.dataDoc[parameter]) : 'B' + BoolCast(this.dataDoc[parameter])}> + value={typeof this.rootDoc[parameter] === 'string' ? 'S' + StrCast(this.rootDoc[parameter]) : typeof this.rootDoc[parameter] === 'number' ? 'N' + NumCast(this.rootDoc[parameter]) : 'B' + BoolCast(this.rootDoc[parameter])}> {types.map(type => (