aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/documents/DocumentTypes.ts1
-rw-r--r--src/client/documents/Documents.ts12
-rw-r--r--src/client/util/ScriptManager.ts63
-rw-r--r--src/client/util/Scripting.ts9
-rw-r--r--src/client/views/nodes/ScriptingBox.tsx39
5 files changed, 113 insertions, 11 deletions
diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts
index 06d35038a..7ba21b2f6 100644
--- a/src/client/documents/DocumentTypes.ts
+++ b/src/client/documents/DocumentTypes.ts
@@ -34,5 +34,6 @@ export enum DocumentType {
COMPARISON = "comparison", // before/after view with slider (view of 2 images)
LINKDB = "linkdb", // database of links ??? why do we have this
+ SCRIPTDB = "scriptdb", // database of scripts
RECOMMENDATION = "recommendation", // view of a recommendation
} \ No newline at end of file
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 38fe04534..27fbbc433 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -262,6 +262,11 @@ export namespace Docs {
layout: { view: EmptyBox, dataField: defaultDataKey },
options: { childDropAction: "alias", title: "Global Link Database" }
}],
+ [DocumentType.SCRIPTDB, {
+ data: new List<Doc>(),
+ layout: { view: EmptyBox, dataField: defaultDataKey },
+ options: { childDropAction: "alias", title: "Global Script Database" }
+ }],
[DocumentType.SCRIPTING, {
layout: { view: ScriptingBox, dataField: defaultDataKey }
}],
@@ -361,6 +366,13 @@ export namespace Docs {
}
/**
+ * A collection of all scripts in the database
+ */
+ export function MainScriptDocument() {
+ return Prototypes.get(DocumentType.SCRIPTDB);
+ }
+
+ /**
* This is a convenience method that is used to initialize
* prototype documents for the first time.
*
diff --git a/src/client/util/ScriptManager.ts b/src/client/util/ScriptManager.ts
new file mode 100644
index 000000000..5bddb44ca
--- /dev/null
+++ b/src/client/util/ScriptManager.ts
@@ -0,0 +1,63 @@
+import { Doc, DocListCast } from "../../fields/Doc";
+import { List } from "../../fields/List";
+import { Docs } from "../documents/Documents";
+import { Scripting, ScriptParam } from "./Scripting";
+import { StrCast } from "../../fields/Types";
+
+
+export class ScriptManager {
+
+ private static _instance: ScriptManager;
+ public static get Instance(): ScriptManager {
+ return this._instance || (this._instance = new this());
+ }
+ private constructor() {
+ }
+
+ public get ScriptManagerDoc(): Doc | undefined {
+ return Docs.Prototypes.MainScriptDocument();
+ }
+
+ public getAllScripts(): Doc[] {
+ const sdoc = ScriptManager.Instance.ScriptManagerDoc;
+ if (sdoc) {
+ const docs = DocListCast(sdoc.data);
+ return docs;
+ }
+ return [];
+ }
+
+ public addScript(scriptDoc: Doc): boolean {
+ const scriptList = ScriptManager.Instance.getAllScripts();
+ scriptList.push(scriptDoc);
+ if (ScriptManager.Instance.ScriptManagerDoc) {
+ ScriptManager.Instance.ScriptManagerDoc.data = new List<Doc>(scriptList);
+ return true;
+ }
+ return false;
+ }
+
+ public deleteScript(scriptDoc: Doc): boolean {
+ const scriptList = ScriptManager.Instance.getAllScripts();
+ const index = ScriptManager.Instance.getAllScripts().indexOf(scriptDoc);
+ if (index > -1) {
+ scriptList.splice(index, 1);
+ if (ScriptManager.Instance.ScriptManagerDoc) {
+ ScriptManager.Instance.ScriptManagerDoc.data = new List<Doc>(scriptList);
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+const scriptList = ScriptManager.Instance.getAllScripts();
+
+scriptList.forEach((scriptDoc: Doc) => {
+
+ const p = scriptDoc.compileParams?.reduce((o: ScriptParam, p: string) => { o[p] = "any"; return o; }, {} as ScriptParam);
+ const f = new Function(...Array.from(Object.keys(p)), StrCast(scriptDoc.rawScript));
+
+ Scripting.addGlobal(f, StrCast(scriptDoc.description), StrCast(p), StrCast(scriptDoc.name));
+
+}); \ No newline at end of file
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index 817e6b29d..5619b22b0 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -51,8 +51,9 @@ export namespace Scripting {
export function addGlobal(name: string, global: any): void;
export function addGlobal(global: { name: string }, decription?: string, params?: any): void;
+ export function addGlobal(global: { name: string }, decription?: string, params?: any, name?: any): void;
- export function addGlobal(nameOrGlobal: any, global?: any, params?: any) {
+ export function addGlobal(nameOrGlobal: any, global?: any, params?: any, name?: any) {
let n: any;
let obj: any;
@@ -61,12 +62,16 @@ export namespace Scripting {
n = nameOrGlobal;
obj = global;
} else {
- n = nameOrGlobal.name;
obj = [nameOrGlobal];
obj.push(global);
if (params) {
obj.push(params);
}
+ if (name) {
+ n = name;
+ } else {
+ n = nameOrGlobal.name;
+ }
}
} else if (nameOrGlobal && typeof nameOrGlobal.name === "string") {
n = nameOrGlobal.name;
diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx
index 149640c07..6f94ae8f9 100644
--- a/src/client/views/nodes/ScriptingBox.tsx
+++ b/src/client/views/nodes/ScriptingBox.tsx
@@ -22,6 +22,7 @@ const _global = (window /* browser */ || global /* node */) as any;
import ReactTextareaAutocomplete from "@webscopeio/react-textarea-autocomplete";
import "@webscopeio/react-textarea-autocomplete/style.css";
+import { ScriptManager } from "../../util/ScriptManager";
const ScriptingSchema = createSchema({});
@@ -184,23 +185,30 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps, Sc
this.dataDoc.documentText = this.rawScript;
this.dataDoc.data = result.compiled ? new ScriptField(result) : undefined;
this.onError(result.compiled ? undefined : result.errors);
+ if (result.compiled) {
+ return true;
+ } else {
+ return false;
+ }
}
// checks if the script compiles and then runs the script
@action
onRun = () => {
- this.onCompile();
- const bindings: { [name: string]: any } = {};
- this.paramsNames.forEach(key => bindings[key] = this.dataDoc[key]);
- // binds vars so user doesnt have to refer to everything as self.<var>
- ScriptCast(this.dataDoc.data, null)?.script.run({ self: this.rootDoc, this: this.layoutDoc, ...bindings }, this.onError);
+ if (this.onCompile()) {
+ const bindings: { [name: string]: any } = {};
+ this.paramsNames.forEach(key => bindings[key] = this.dataDoc[key]);
+ // binds vars so user doesnt have to refer to everything as self.<var>
+ ScriptCast(this.dataDoc.data, null)?.script.run({ self: this.rootDoc, this: this.layoutDoc, ...bindings }, this.onError);
+ }
}
// checks if the script compiles and switches to applied UI
@action
onApply = () => {
- this.onCompile();
- this._applied = true;
+ if (this.onCompile()) {
+ this._applied = true;
+ }
}
@action
@@ -208,6 +216,17 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps, Sc
this._applied = false;
}
+ @action
+ onSave = () => {
+ if (this.onCompile()) {
+ this.dataDoc.funcName = "testingTitle";
+ this.dataDoc.descripition = "description test";
+ ScriptManager.Instance.addScript(this.dataDoc);
+ } else {
+ this._errorMessage = "Can not save script, does not compile";
+ }
+ }
+
// overlays document numbers (ex. d32) over all documents when clicked on
onFocus = () => {
this._overlayDisposer?.();
@@ -653,8 +672,10 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps, Sc
renderScriptingTools() {
const buttonStyle = "scriptingBox-button" + (this.rootDoc.layoutKey === "layout_onClick" ? "third" : "");
return <div className="scriptingBox-toolbar">
- <button className={buttonStyle} onPointerDown={e => { this.onCompile(); e.stopPropagation(); }}>Compile</button>
- <button className={buttonStyle} onPointerDown={e => { this.onApply(); e.stopPropagation(); }}>Apply</button>
+ <button className={buttonStyle} style={{ width: "33%" }} onPointerDown={e => { this.onCompile(); e.stopPropagation(); }}>Compile</button>
+ <button className={buttonStyle} style={{ width: "33%" }} onPointerDown={e => { this.onApply(); e.stopPropagation(); }}>Apply</button>
+ <button className={buttonStyle} style={{ width: "33%" }} onPointerDown={e => { this.onSave(); e.stopPropagation(); }}>Save</button>
+
{this.rootDoc.layoutKey !== "layout_onClick" ? (null) :
<button className={buttonStyle} onPointerDown={e => { this.onFinish(); e.stopPropagation(); }}>Finish</button>}
</div>;