aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/ScriptingRepl.tsx
diff options
context:
space:
mode:
authorNathan-SR <144961007+Nathan-SR@users.noreply.github.com>2024-10-01 03:58:47 -0400
committerNathan-SR <144961007+Nathan-SR@users.noreply.github.com>2024-10-01 03:58:47 -0400
commit6d35629dd8f997208130981aac1daf36bc83b134 (patch)
tree7b7e3baac15e5f7b4fcb48d90372c48d4552ae4c /src/client/views/ScriptingRepl.tsx
parentcf45abf8ada938caddb226c825166d4acdee3086 (diff)
parentba01c7376ed4a2b817a26a430faf4041524aef35 (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.tsx54
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>
))}