diff options
Diffstat (limited to 'src/client/views/nodes/ScriptingBox.tsx')
-rw-r--r-- | src/client/views/nodes/ScriptingBox.tsx | 85 |
1 files changed, 47 insertions, 38 deletions
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<ViewBoxAnnotatable constructor(props: any) { super(props); + if (!this.compileParams.length) { + const params = ScriptCast(this.rootDoc[this.props.fieldKey])?.script.options.params as { [key: string]: any }; + if (params) { + this.compileParams = Array.from(Object.keys(params)) + .filter(p => !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<ViewBoxAnnotatable return this.compileParams.map(p => 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<string>(value); + Doc.SetInPlace(this.rootDoc, this.props.fieldKey + '-params', new List<string>(value), true); } getValue(result: any, descrip: boolean) { @@ -107,8 +115,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable @action componentDidMount() { - this.rawScript = ScriptCast(this.dataDoc[this.props.fieldKey])?.script?.originalScript ?? this.rawScript; - + this.rawText = this.rawScript; const observer = new _global.ResizeObserver( action((entries: any) => { const area = document.querySelector('textarea'); @@ -171,13 +178,13 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable const params: ScriptParam = {}; this.compileParams.forEach(p => (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<ViewBoxAnnotatable 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.rootDoc[key])); // binds vars so user doesnt have to refer to everything as self.<var> - 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<ViewBoxAnnotatable // 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]; + 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<ViewBoxAnnotatable 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'; + 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<ViewBoxAnnotatable maxHeight={72} height={35} fontSize={14} - contents={this.dataDoc[parameter]?.title ?? 'undefined'} - GetValue={() => 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<ViewBoxAnnotatable const results = script.compiled && script.run(); if (results && results.success) { this._errorMessage = ''; - this.dataDoc[parameter] = results.result; + Doc.SetInPlace(this.rootDoc, parameter, results.result, true); return true; } this._errorMessage = 'invalid document'; @@ -354,7 +361,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable // rendering when a string's value can be set in applied UI renderBasicType(parameter: string, isNum: boolean) { - const strVal = isNum ? NumCast(this.dataDoc[parameter]).toString() : StrCast(this.dataDoc[parameter]); + const strVal = isNum ? NumCast(this.rootDoc[parameter]).toString() : StrCast(this.rootDoc[parameter]); return ( <div className="scriptingBox-paramInputs" style={{ overflowY: 'hidden' }}> <EditableView @@ -368,7 +375,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable const setValue = isNum ? parseInt(value) : value; if (setValue !== undefined && setValue !== ' ') { this._errorMessage = ''; - this.dataDoc[parameter] = setValue; + Doc.SetInPlace(this.rootDoc, parameter, setValue, true); return true; } this._errorMessage = 'invalid input'; @@ -389,7 +396,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable className="scriptingBox-viewPicker" onPointerDown={e => 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 => ( <option className="scriptingBox-viewOption" value={(typeof type === 'string' ? 'S' : typeof type === 'number' ? 'N' : 'B') + type}> {' '} @@ -442,7 +449,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable @action handleFunc(pos: number) { - const scriptString = this.rawScript.slice(0, pos - 2); + const scriptString = this.rawText.slice(0, pos - 2); this._currWord = scriptString.split(' ')[scriptString.split(' ').length - 1]; this._suggestions = [StrCast(this._scriptingParams[this._currWord])]; return this._suggestions; @@ -474,7 +481,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable } getSuggestedParams(pos: number) { - const firstScript = this.rawScript.slice(0, pos); + const firstScript = this.rawText.slice(0, pos); const indexP = firstScript.lastIndexOf('.'); const indexS = firstScript.lastIndexOf(' '); const func = firstScript.slice((indexP > indexS ? indexP : indexS) + 1, firstScript.length + 1); @@ -494,8 +501,9 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable @action keyHandler(e: any, pos: number) { + e.stopPropagation(); if (this._lastChar === 'Enter') { - this.rawScript = this.rawScript + ' '; + this.rawText = this.rawText + ' '; } if (e.key === '(') { this.suggestionPos(); @@ -504,7 +512,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable this._scriptSuggestedParams = this.getSuggestedParams(pos); if (this._scriptParamsText !== undefined && this._scriptParamsText.length > 0) { - if (this.rawScript[pos - 2] !== '(') { + if (this.rawText[pos - 2] !== '(') { this._paramSuggestion = true; } } @@ -515,22 +523,22 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable if (this._lastChar === '(') { this._paramSuggestion = false; } else if (this._lastChar === ')') { - if (this.rawScript.slice(0, this.rawScript.length - 1).split('(').length - 1 > this.rawScript.slice(0, this.rawScript.length - 1).split(')').length - 1) { + if (this.rawText.slice(0, this.rawText.length - 1).split('(').length - 1 > this.rawText.slice(0, this.rawText.length - 1).split(')').length - 1) { if (this._scriptParamsText.length > 0) { this._paramSuggestion = true; } } } - } else if (this.rawScript.split('(').length - 1 <= this.rawScript.split(')').length - 1) { + } else if (this.rawText.split('(').length - 1 <= this.rawText.split(')').length - 1) { this._paramSuggestion = false; } } - this._lastChar = e.key === 'Backspace' ? this.rawScript[this.rawScript.length - 2] : e.key; + this._lastChar = e.key === 'Backspace' ? this.rawText[this.rawText.length - 2] : e.key; if (this._paramSuggestion) { const parameters = this._scriptParamsText.split(','); - const index = this.rawScript.lastIndexOf('('); - const enteredParams = this.rawScript.slice(index, this.rawScript.length); + const index = this.rawText.lastIndexOf('('); + const enteredParams = this.rawText.slice(index, this.rawText.length); const splitEntered = enteredParams.split(','); const numEntered = splitEntered.length; @@ -564,15 +572,16 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable handlePosChange(number: any) { this._caretPos = number; if (this._caretPos === 0) { - this.rawScript = ' ' + this.rawScript; + this.rawText = ' ' + this.rawText; } else if (this._spaced) { this._spaced = false; - if (this.rawScript[this._caretPos - 1] === ' ') { - this.rawScript = this.rawScript.slice(0, this._caretPos - 1) + this.rawScript.slice(this._caretPos, this.rawScript.length); + if (this.rawText[this._caretPos - 1] === ' ') { + this.rawText = this.rawText.slice(0, this._caretPos - 1) + this.rawText.slice(this._caretPos, this.rawText.length); } } } + @observable rawText: string = ''; @computed({ keepAlive: true }) get renderScriptingBox() { TraceMobx(); return ( @@ -583,8 +592,8 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable placeholder="write your script here" onFocus={this.onFocus} onBlur={() => this._overlayDisposer?.()} - onChange={(e: any) => (this.rawScript = e.target.value)} - value={this.rawScript} + onChange={action((e: any) => (this.rawText = e.target.value))} + value={this.rawText} movePopupAsYouType={true} loadingComponent={() => <span>Loading</span>} trigger={{ |