diff options
author | Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> | 2024-10-01 03:58:47 -0400 |
---|---|---|
committer | Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> | 2024-10-01 03:58:47 -0400 |
commit | 6d35629dd8f997208130981aac1daf36bc83b134 (patch) | |
tree | 7b7e3baac15e5f7b4fcb48d90372c48d4552ae4c /src/client/views/ScriptingRepl.tsx | |
parent | cf45abf8ada938caddb226c825166d4acdee3086 (diff) | |
parent | ba01c7376ed4a2b817a26a430faf4041524aef35 (diff) |
Merge branch 'master' of https://github.com/brown-dash/Dash-Web into nathan-starter
Diffstat (limited to 'src/client/views/ScriptingRepl.tsx')
-rw-r--r-- | src/client/views/ScriptingRepl.tsx | 54 |
1 files changed, 29 insertions, 25 deletions
diff --git a/src/client/views/ScriptingRepl.tsx b/src/client/views/ScriptingRepl.tsx index 1a2eb460f..2de867746 100644 --- a/src/client/views/ScriptingRepl.tsx +++ b/src/client/views/ScriptingRepl.tsx @@ -1,6 +1,4 @@ /* eslint-disable react/no-array-index-key */ -/* eslint-disable jsx-a11y/no-static-element-interactions */ -/* eslint-disable jsx-a11y/click-events-have-key-events */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; @@ -14,21 +12,26 @@ import { OverlayView } from './OverlayView'; import './ScriptingRepl.scss'; import { DocumentIconContainer } from './nodes/DocumentIcon'; import { DocumentView } from './nodes/DocumentView'; +import { returnFalse, setupMoveUpEvents } from '../../ClientUtils'; +import { emptyFunction } from '../../Utils'; +import { ObjectField } from '../../fields/ObjectField'; +import { RefField } from '../../fields/RefField'; +import { Doc, FieldResult, FieldType, Opt } from '../../fields/Doc'; interface replValueProps { scrollToBottom: () => void; - value: any; + value: Opt<FieldResult | Promise<RefField | undefined>>; name?: string; } @observer export class ScriptingValueDisplay extends ObservableReactComponent<replValueProps> { - constructor(props: any) { + constructor(props: replValueProps) { super(props); makeObservable(this); } render() { - const val = this._props.name ? this._props.value[this._props.name] : this._props.value; + const val = this._props.value instanceof Doc && this._props.name ? this._props.value[this._props.name] : this._props.value; const title = (name: string) => ( <> {this._props.name ? <b>{this._props.name} : </b> : <> </>} @@ -47,13 +50,14 @@ export class ScriptingValueDisplay extends ObservableReactComponent<replValuePro } interface ReplProps { scrollToBottom: () => void; - value: { [key: string]: any }; + value: Opt<FieldResult | Promise<RefField | undefined>>; name?: string; } +@observer export class ScriptingObjectDisplay extends ObservableReactComponent<ReplProps> { @observable collapsed = true; - constructor(props: any) { + constructor(props: ReplProps) { super(props); makeObservable(this); } @@ -74,10 +78,12 @@ export class ScriptingObjectDisplay extends ObservableReactComponent<ReplProps> {name} </> ); + if (val === undefined) return '--undefined--'; + if (val instanceof Promise) return '...Promise...'; if (this.collapsed) { return ( <div className="scriptingObject-collapsed"> - <span onClick={this.toggle} className="scriptingObject-icon scriptingObject-iconCollapsed"> + <span onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, this.toggle)} className="scriptingObject-icon scriptingObject-iconCollapsed"> <FontAwesomeIcon icon="caret-right" size="sm" /> </span> {title} (+{Object.keys(val).length}) @@ -94,8 +100,7 @@ export class ScriptingObjectDisplay extends ObservableReactComponent<ReplProps> </div> <div className="scriptingObject-fields"> {Object.keys(val).map(key => ( - // eslint-disable-next-line react/jsx-props-no-spreading - <ScriptingValueDisplay {...this._props} name={key} /> + <ScriptingValueDisplay name={key} key={key} value={this._props.value} scrollToBottom={this._props.scrollToBottom} /> ))} </div> </div> @@ -104,13 +109,13 @@ export class ScriptingObjectDisplay extends ObservableReactComponent<ReplProps> } @observer -export class ScriptingRepl extends ObservableReactComponent<{}> { - constructor(props: any) { +export class ScriptingRepl extends ObservableReactComponent<object> { + constructor(props: object) { super(props); makeObservable(this); } - @observable private commands: { command: string; result: any }[] = []; + @observable private commands: { command: string; result: unknown }[] = []; private commandsHistory: string[] = []; @observable private commandString: string = ''; @@ -120,13 +125,11 @@ export class ScriptingRepl extends ObservableReactComponent<{}> { private commandsRef = React.createRef<HTMLDivElement>(); - private args: any = {}; - getTransformer = (): Transformer => ({ transformer: context => { const knownVars: { [name: string]: number } = {}; const usedDocuments: number[] = []; - ScriptingGlobals.getGlobals().forEach((global: any) => { + ScriptingGlobals.getGlobals().forEach((global: string) => { knownVars[global] = 1; }); return root => { @@ -168,7 +171,7 @@ export class ScriptingRepl extends ObservableReactComponent<{}> { switch (e.key) { case 'Enter': { e.stopPropagation(); - const docGlobals: { [name: string]: any } = {}; + const docGlobals: { [name: string]: FieldType } = {}; DocumentView.allViews().forEach((dv, i) => { docGlobals[`d${i}`] = dv.Document; }); @@ -176,19 +179,20 @@ export class ScriptingRepl extends ObservableReactComponent<{}> { const script = CompileScript(this.commandString, { typecheck: false, addReturn: true, editable: true, params: { args: 'any' }, transformer: this.getTransformer(), globals }); if (!script.compiled) { this.commands.push({ command: this.commandString, result: script.errors }); + this.maybeScrollToBottom(); return; } - const result = undoable(() => script.run({ args: this.args }, () => this.commands.push({ command: this.commandString, result: e.toString() })), 'run:' + this.commandString)(); + const result = undoable(() => script.run({}, e => this.commands.push({ command: this.commandString, result: e as string })), 'run:' + this.commandString)(); if (result.success) { this.commands.push({ command: this.commandString, result: result.result }); this.commandsHistory.push(this.commandString); - this.maybeScrollToBottom(); - this.commandString = ''; this.commandBuffer = ''; this.historyIndex = -1; } + + this.maybeScrollToBottom(); break; } case 'ArrowUp': { @@ -232,7 +236,7 @@ export class ScriptingRepl extends ObservableReactComponent<{}> { private shouldScroll: boolean = false; private maybeScrollToBottom = () => { const ele = this.commandsRef.current; - if (ele && ele.scrollTop === ele.scrollHeight - ele.offsetHeight) { + if (ele && Math.abs(Math.ceil(ele.scrollTop) - (ele.scrollHeight - ele.offsetHeight)) < 2) { this.shouldScroll = true; this.forceUpdate(); } @@ -240,14 +244,14 @@ export class ScriptingRepl extends ObservableReactComponent<{}> { private scrollToBottom() { const ele = this.commandsRef.current; - ele && ele.scroll({ behavior: 'auto', top: ele.scrollHeight }); + ele?.scroll({ behavior: 'smooth', top: ele.scrollHeight }); } - componentDidUpdate(prevProps: Readonly<{}>) { + componentDidUpdate(prevProps: Readonly<object>) { super.componentDidUpdate(prevProps); if (this.shouldScroll) { this.shouldScroll = false; - this.scrollToBottom(); + setTimeout(() => this.scrollToBottom(), 0); } } @@ -269,7 +273,7 @@ export class ScriptingRepl extends ObservableReactComponent<{}> { {command || <br />} </div> <div className="scriptingRepl-commandResult" style={{ background: SnappingManager.userBackgroundColor }}> - <ScriptingValueDisplay scrollToBottom={this.maybeScrollToBottom} value={result} /> + <ScriptingValueDisplay scrollToBottom={this.maybeScrollToBottom} value={result as ObjectField | RefField} /> </div> </div> ))} |