From 9a795d09127d10f23e3992f899265fd227e49af4 Mon Sep 17 00:00:00 2001 From: Mohammad Amoush Date: Sun, 1 Mar 2020 16:12:06 -0500 Subject: basic changes finished --- src/client/util/Scripting.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/client/util/Scripting.ts') diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 0fa96963e..ca770f897 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -89,9 +89,9 @@ const _scriptingGlobals: { [name: string]: any } = {}; let scriptingGlobals: { [name: string]: any } = _scriptingGlobals; function Run(script: string | undefined, customParams: string[], diagnostics: any[], originalScript: string, options: ScriptOptions): CompileResult { - const errors = diagnostics.some(diag => diag.category === ts.DiagnosticCategory.Error); - if ((options.typecheck !== false && errors) || !script) { - return { compiled: false, errors: diagnostics }; + const errors = diagnostics.filter(diag => diag.category === ts.DiagnosticCategory.Error); + if ((options.typecheck !== false && errors.length) || !script) { + return { compiled: false, errors }; } const paramNames = Object.keys(scriptingGlobals); @@ -273,6 +273,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp const result = Run(outputText, paramNames, diagnostics, script, options); + if (options.globals) { Scripting.resetScriptingGlobals(); } -- cgit v1.2.3-70-g09d2 From b21db9d40c1619df5455ba8ffe3ef76913cc92de Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 8 Apr 2020 19:14:47 -0400 Subject: added scripting box --- src/client/documents/Documents.ts | 4 +- src/client/util/Scripting.ts | 8 +- src/client/views/MainView.tsx | 3 +- src/client/views/nodes/ScriptingBox.scss | 33 +++++ src/client/views/nodes/ScriptingBox.tsx | 137 ++++++++++++--------- .../authentication/models/current_user_utils.ts | 1 + 6 files changed, 123 insertions(+), 63 deletions(-) (limited to 'src/client/util/Scripting.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 5231dbb8c..5eca71ca9 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -509,8 +509,8 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.PRES), initial, options); } - export function ScriptingDocument(url: string, options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocumentType.SCRIPTING), new YoutubeField(new URL(url)), options); + export function ScriptingDocument(options: DocumentOptions = {}) { + return InstanceFromProto(Prototypes.get(DocumentType.SCRIPTING), "", options); } export function VideoDocument(url: string, options: DocumentOptions = {}) { diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index cf04c44ca..f97d91d10 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -89,9 +89,9 @@ const _scriptingGlobals: { [name: string]: any } = {}; let scriptingGlobals: { [name: string]: any } = _scriptingGlobals; function Run(script: string | undefined, customParams: string[], diagnostics: any[], originalScript: string, options: ScriptOptions): CompileResult { - const errors = diagnostics.some(diag => diag.category === ts.DiagnosticCategory.Error); - if ((options.typecheck !== false && errors) || !script) { - return { compiled: false, errors: diagnostics }; + const errors = diagnostics.filter(diag => diag.category === ts.DiagnosticCategory.Error); + if ((options.typecheck !== false && errors.length) || !script) { + return { compiled: false, errors }; } const paramNames = Object.keys(scriptingGlobals); @@ -201,7 +201,7 @@ export interface ScriptOptions { capturedVariables?: { [name: string]: Field }; // list of captured variables typecheck?: boolean; // should the compiler perform typechecking editable?: boolean; // can the script edit Docs - traverser?: TraverserParam; + traverser?: TraverserParam; transformer?: Transformer; // does the editor display a text label by each document that can be used as a captured document reference globals?: { [name: string]: any }; } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 7c9f47fe4..1edfc871f 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,5 +1,5 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt, faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faThumbtack, faTree, faTv, faUndoAlt, faVideo } from '@fortawesome/free-solid-svg-icons'; +import { faTerminal, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt, faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faThumbtack, faTree, faTv, faUndoAlt, faVideo } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; @@ -101,6 +101,7 @@ export class MainView extends React.Component { } } + library.add(faTerminal); library.add(faFileAlt); library.add(faStickyNote); library.add(faFont); diff --git a/src/client/views/nodes/ScriptingBox.scss b/src/client/views/nodes/ScriptingBox.scss index e69de29bb..f31c72bb2 100644 --- a/src/client/views/nodes/ScriptingBox.scss +++ b/src/client/views/nodes/ScriptingBox.scss @@ -0,0 +1,33 @@ +.scriptingBox-outerDiv { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + pointer-events: all; + background-color: rgb(241, 239, 235); + padding: 10px; + .scriptingBox-inputDiv { + display: flex; + flex-direction: column; + height: calc(100% - 30px); + .scriptingBox-errorMessage { + overflow: auto; + } + .scriptingBox-textArea { + width: 100%; + height: 100%; + box-sizing: border-box; + resize: none; + padding: 7px; + } + } + + .scriptingBox-toolbar { + width: 100%; + height: 30px; + .scriptingBox-button { + width: 50% + } + } +} + diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx index a2dd134ed..74d9c2e94 100644 --- a/src/client/views/nodes/ScriptingBox.tsx +++ b/src/client/views/nodes/ScriptingBox.tsx @@ -1,71 +1,96 @@ -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faEdit } from '@fortawesome/free-regular-svg-icons'; -import { computed } from 'mobx'; -import { observer } from 'mobx-react'; -import * as React from 'react'; -import { Doc } from '../../../new_fields/Doc'; -import { documentSchema } from '../../../new_fields/documentSchemas'; +import { action, observable, computed } from "mobx"; +import { observer } from "mobx-react"; +import * as React from "react"; +import { Opt } from "../../../new_fields/Doc"; +import { documentSchema } from "../../../new_fields/documentSchemas"; +import { createSchema, makeInterface } from "../../../new_fields/Schema"; +import { ScriptField } from "../../../new_fields/ScriptField"; +import { StrCast, ScriptCast } from "../../../new_fields/Types"; +import { returnTrue } from "../../../Utils"; +import { InteractionUtils } from "../../util/InteractionUtils"; import { CompileScript } from "../../util/Scripting"; -import { ScriptBox } from '../ScriptBox'; -import { createSchema, listSpec, makeInterface } from '../../../new_fields/Schema'; -import { ScriptField } from '../../../new_fields/ScriptField'; -import { BoolCast, ScriptCast } from '../../../new_fields/Types'; -import { DocComponent } from '../DocComponent'; -import { FieldView, FieldViewProps } from './FieldView'; -import './ScriptingBox.scss'; -import { DocumentIconContainer } from './DocumentIcon'; - - -library.add(faEdit as any); +import { DocAnnotatableComponent } from "../DocComponent"; +import { EditableView } from "../EditableView"; +import { FieldView, FieldViewProps } from "../nodes/FieldView"; +import "./ScriptingBox.scss"; const ScriptingSchema = createSchema({ - onClick: ScriptField, - buttonParams: listSpec("string"), - text: "string" }); type ScriptingDocument = makeInterface<[typeof ScriptingSchema, typeof documentSchema]>; const ScriptingDocument = makeInterface(ScriptingSchema, documentSchema); @observer -export class ScriptingBox extends DocComponent(ScriptingDocument) { - public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ScriptingBox, fieldKey); } +export class ScriptingBox extends DocAnnotatableComponent(ScriptingDocument) { + protected multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer | undefined; + public static LayoutString(fieldStr: string) { return FieldView.LayoutString(ScriptingBox, fieldStr); } - @computed get dataDoc() { - return this.props.DataDoc && - (this.Document.isTemplateForField || BoolCast(this.props.DataDoc.isTemplateForField) || - this.props.DataDoc.layout === this.props.Document) ? this.props.DataDoc : Doc.GetProto(this.props.Document); + @observable private _errorMessage: string = ""; + @computed get rawScript() { return StrCast(this.dataDoc[this.props.fieldKey + "-raw"]); } + set rawScript(value) { this.dataDoc[this.props.fieldKey + "-raw"] = value; } + + @action + componentDidMount() { + this.rawScript = ScriptCast(this.dataDoc[this.props.fieldKey])?.script?.originalScript || this.rawScript; } - specificContextMenu = (e: React.MouseEvent): void => { } + @action + onChange = (e: React.ChangeEvent) => { + this.rawScript = e.target.value; + } - render() { - const script = ScriptCast(this.props.Document[this.props.fieldKey]); - let originalText: string | undefined = undefined; - if (script) { - originalText = script.script.originalScript; + @action + onError = (error: any) => { + this._errorMessage = (error as any).map((e: any) => e.messageText).join(" "); + } + + @action + onCompile = () => { + const result = CompileScript(this.rawScript, {}); + this._errorMessage = ""; + if (result.compiled) { + this._errorMessage = ""; + this.dataDoc[this.props.fieldKey] = new ScriptField(result); } - return !(this.props.Document instanceof Doc) ? (null) : - { }} - onCancel={() => { }} - onSave={(text, onError) => { - if (!text) { - this.dataDoc[this.props.fieldKey] = undefined; - } else { - const script = CompileScript(text, { - params: { this: Doc.name }, - typecheck: false, - editable: true, - transformer: DocumentIconContainer.getTransformer() - }); - if (!script.compiled) { - onError(script.errors.map(error => error.messageText).join("\n")); - } - else { - this.dataDoc[this.props.fieldKey] = new ScriptField(script); - } - } - }} showDocumentIcons />; + else { + this.dataDoc[this.props.fieldKey] = undefined; + this.onError(result.errors); + } + } + + @action + onRun = () => { + this.onCompile(); + ScriptCast(this.dataDoc[this.props.fieldKey])?.script.run({}, + (err: any) => { + this._errorMessage = ""; + this.onError(err); + }); + } + + render() { + let onFocus: Opt<() => void> = undefined, onBlur: Opt<() => void> = undefined; + const params = ""} + SetValue={returnTrue} + />; + return ( +
this.props.isSelected() && e.stopPropagation()} onWheel={(e) => this.props.isSelected() && e.stopPropagation()}> +
+ -
{this._errorMessage}
+
{params}
- - + +
); @@ -179,4 +123,4 @@ export class ScriptBox extends DocAnnotatableComponent; overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, { x: 400, y: 200, width: 500, height: 400, title }); } -} +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From df170f53e2c88bd77a552e42b2eba5470b15cb03 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 9 Apr 2020 02:31:19 -0400 Subject: cleaned up some scriptingBox code -- added parameters --- src/client/util/Scripting.ts | 8 ++++ src/client/views/ScriptBox.tsx | 4 +- src/client/views/nodes/ScriptingBox.scss | 3 ++ src/client/views/nodes/ScriptingBox.tsx | 81 ++++++++++++++++---------------- 4 files changed, 52 insertions(+), 44 deletions(-) (limited to 'src/client/util/Scripting.ts') diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index f97d91d10..57d22eaf8 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -24,6 +24,8 @@ export interface ScriptError { export type ScriptResult = ScriptSucccess | ScriptError; +export type ScriptParam = { [name: string]: string }; + export interface CompiledScript { readonly compiled: true; readonly originalScript: string; @@ -37,6 +39,12 @@ export interface CompileError { } export type CompileResult = CompiledScript | CompileError; +export function isCompileError(toBeDetermined: CompileResult): toBeDetermined is CompileError { + if ((toBeDetermined as CompileError).errors) { + return true + } + return false +} export namespace Scripting { export function addGlobal(global: { name: string }): void; diff --git a/src/client/views/ScriptBox.tsx b/src/client/views/ScriptBox.tsx index 0352ddaca..6735a8b54 100644 --- a/src/client/views/ScriptBox.tsx +++ b/src/client/views/ScriptBox.tsx @@ -43,9 +43,7 @@ export class ScriptBox extends React.Component { overlayDisposer?: () => void; onFocus = () => { - if (this.overlayDisposer) { - this.overlayDisposer(); - } + this.overlayDisposer?.(); this.overlayDisposer = OverlayView.Instance.addElement(, { x: 0, y: 0 }); } diff --git a/src/client/views/nodes/ScriptingBox.scss b/src/client/views/nodes/ScriptingBox.scss index f31c72bb2..678a1a22d 100644 --- a/src/client/views/nodes/ScriptingBox.scss +++ b/src/client/views/nodes/ScriptingBox.scss @@ -13,6 +13,9 @@ .scriptingBox-errorMessage { overflow: auto; } + .scripting-params { + background: "beige"; + } .scriptingBox-textArea { width: 100%; height: 100%; diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx index 74d9c2e94..93956592f 100644 --- a/src/client/views/nodes/ScriptingBox.tsx +++ b/src/client/views/nodes/ScriptingBox.tsx @@ -1,22 +1,21 @@ import { action, observable, computed } from "mobx"; import { observer } from "mobx-react"; import * as React from "react"; -import { Opt } from "../../../new_fields/Doc"; import { documentSchema } from "../../../new_fields/documentSchemas"; -import { createSchema, makeInterface } from "../../../new_fields/Schema"; +import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema"; import { ScriptField } from "../../../new_fields/ScriptField"; -import { StrCast, ScriptCast } from "../../../new_fields/Types"; -import { returnTrue } from "../../../Utils"; +import { StrCast, ScriptCast, Cast } from "../../../new_fields/Types"; import { InteractionUtils } from "../../util/InteractionUtils"; -import { CompileScript } from "../../util/Scripting"; +import { CompileScript, isCompileError, ScriptParam } from "../../util/Scripting"; import { DocAnnotatableComponent } from "../DocComponent"; import { EditableView } from "../EditableView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./ScriptingBox.scss"; +import { OverlayView } from "../OverlayView"; +import { DocumentIconContainer } from "./DocumentIcon"; +import { List } from "../../../new_fields/List"; -const ScriptingSchema = createSchema({ -}); - +const ScriptingSchema = createSchema({}); type ScriptingDocument = makeInterface<[typeof ScriptingSchema, typeof documentSchema]>; const ScriptingDocument = makeInterface(ScriptingSchema, documentSchema); @@ -25,66 +24,66 @@ export class ScriptingBox extends DocAnnotatableComponent void; + @observable private _errorMessage: string = ""; + @computed get rawScript() { return StrCast(this.dataDoc[this.props.fieldKey + "-raw"]); } + @computed get compileParams() { return Cast(this.dataDoc[this.props.fieldKey + "-params"], listSpec("string"), []); } set rawScript(value) { this.dataDoc[this.props.fieldKey + "-raw"] = value; } + set compileParams(value) { this.dataDoc[this.props.fieldKey + "-params"] = value; } @action componentDidMount() { this.rawScript = ScriptCast(this.dataDoc[this.props.fieldKey])?.script?.originalScript || this.rawScript; } - @action - onChange = (e: React.ChangeEvent) => { - this.rawScript = e.target.value; - } - - @action - onError = (error: any) => { - this._errorMessage = (error as any).map((e: any) => e.messageText).join(" "); - } - @action onCompile = () => { - const result = CompileScript(this.rawScript, {}); - this._errorMessage = ""; - if (result.compiled) { - this._errorMessage = ""; - this.dataDoc[this.props.fieldKey] = new ScriptField(result); - } - else { - this.dataDoc[this.props.fieldKey] = undefined; - this.onError(result.errors); - } + const params = this.compileParams.reduce((o: ScriptParam, p: string) => { o[p] = "any"; return o; }, {} as ScriptParam); + const result = CompileScript(this.rawScript, { + editable: true, + transformer: DocumentIconContainer.getTransformer(), + params + }); + this.dataDoc[this.props.fieldKey] = result.compiled ? new ScriptField(result) : undefined; + this._errorMessage = isCompileError(result) ? result.errors.map(e => e.messageText).join("\n") : ""; + return ScriptCast(this.dataDoc[this.props.fieldKey]); } @action onRun = () => { - this.onCompile(); - ScriptCast(this.dataDoc[this.props.fieldKey])?.script.run({}, - (err: any) => { - this._errorMessage = ""; - this.onError(err); - }); + this.onCompile()?.script.run({}, err => this._errorMessage = err.map((e: any) => e.messageText).join("\n")); + } + + onFocus = () => { + this._overlayDisposer?.(); + this._overlayDisposer = OverlayView.Instance.addElement(, { x: 0, y: 0 }); } render() { - let onFocus: Opt<() => void> = undefined, onBlur: Opt<() => void> = undefined; const params = ""} - SetValue={returnTrue} + SetValue={value => { this.compileParams = new List(value.split(" ").filter(s => s !== " ")); return true; }} />; return ( -
this.props.isSelected() && e.stopPropagation()} onWheel={(e) => this.props.isSelected() && e.stopPropagation()}> +
this.props.isSelected(true) && e.stopPropagation()} + onWheel={e => this.props.isSelected(true) && e.stopPropagation()}>
-