From dcfc5d77779117616503c31fc03f36841e25a3f9 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Fri, 24 May 2019 00:56:32 -0400
Subject: Added basic repl page

---
 src/debug/Repl.tsx | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)
 create mode 100644 src/debug/Repl.tsx

(limited to 'src/debug/Repl.tsx')

diff --git a/src/debug/Repl.tsx b/src/debug/Repl.tsx
new file mode 100644
index 000000000..16aef1925
--- /dev/null
+++ b/src/debug/Repl.tsx
@@ -0,0 +1,58 @@
+import * as React from 'react';
+import * as ReactDOM from 'react-dom';
+import { observer } from 'mobx-react';
+import { observable, computed } from 'mobx';
+import { CompileScript } from '../client/util/Scripting';
+
+@observer
+class Repl extends React.Component {
+    @observable text: string = "";
+
+    @observable executedCommands: { command: string, result: any }[] = [];
+
+    onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+        this.text = e.target.value;
+    }
+
+    onKeyDown = (e: React.KeyboardEvent) => {
+        if (e.key === "Enter") {
+            const script = CompileScript(this.text, { addReturn: true, typecheck: false });
+            if (!script.compiled) {
+                this.executedCommands.push({ command: this.text, result: "Compile Error" });
+            } else {
+                const result = script.run();
+                if (result.success) {
+                    this.executedCommands.push({ command: this.text, result: result.result });
+                } else {
+                    this.executedCommands.push({ command: this.text, result: result.error });
+                }
+            }
+            this.text = "";
+        }
+    }
+
+    @computed
+    get commands() {
+        return this.executedCommands.map(command => {
+            return (
+                <div style={{ marginTop: "5px" }}>
+                    <p>{command.command}</p>
+                    <p>{JSON.stringify(command.result)}</p>
+                </div>
+            );
+        });
+    }
+
+    render() {
+        return (
+            <div>
+                <div style={{ verticalAlign: "bottom" }}>
+                    {this.commands}
+                </div>
+                <input style={{ width: "100%", position: "absolute", bottom: "0px" }} value={this.text} onChange={this.onChange} onKeyDown={this.onKeyDown} />
+            </div>
+        );
+    }
+}
+
+ReactDOM.render(<Repl />, document.getElementById("root"));
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2


From 568a3907a1277259eb9a0a5ae62cfcf5d7e60bf2 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Fri, 24 May 2019 01:11:23 -0400
Subject: Fixed firefox user select stuff Made repl multi-line

---
 src/client/views/Main.scss | 3 +++
 src/debug/Repl.tsx         | 6 +++---
 2 files changed, 6 insertions(+), 3 deletions(-)

(limited to 'src/debug/Repl.tsx')

diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss
index 385298e18..57a53c999 100644
--- a/src/client/views/Main.scss
+++ b/src/client/views/Main.scss
@@ -15,6 +15,9 @@ body {
 
 div {
     user-select: none;
+    -moz-user-select: none;
+    -webkit-user-select: none;
+    -ms-user-select: none;
 }
 
 #dash-title {
diff --git a/src/debug/Repl.tsx b/src/debug/Repl.tsx
index 16aef1925..ef00ed466 100644
--- a/src/debug/Repl.tsx
+++ b/src/debug/Repl.tsx
@@ -10,12 +10,12 @@ class Repl extends React.Component {
 
     @observable executedCommands: { command: string, result: any }[] = [];
 
-    onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    onChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
         this.text = e.target.value;
     }
 
     onKeyDown = (e: React.KeyboardEvent) => {
-        if (e.key === "Enter") {
+        if (e.ctrlKey && e.key === "Enter") {
             const script = CompileScript(this.text, { addReturn: true, typecheck: false });
             if (!script.compiled) {
                 this.executedCommands.push({ command: this.text, result: "Compile Error" });
@@ -49,7 +49,7 @@ class Repl extends React.Component {
                 <div style={{ verticalAlign: "bottom" }}>
                     {this.commands}
                 </div>
-                <input style={{ width: "100%", position: "absolute", bottom: "0px" }} value={this.text} onChange={this.onChange} onKeyDown={this.onKeyDown} />
+                <textarea style={{ width: "100%", position: "absolute", bottom: "0px" }} value={this.text} onChange={this.onChange} onKeyDown={this.onKeyDown} />
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From ca95adb9a7b213455ea919b18c70eef0f2334bd9 Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Tue, 28 May 2019 13:46:47 -0400
Subject: Made REPL formatting better

---
 src/debug/Repl.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/debug/Repl.tsx')

diff --git a/src/debug/Repl.tsx b/src/debug/Repl.tsx
index ef00ed466..01acb0e76 100644
--- a/src/debug/Repl.tsx
+++ b/src/debug/Repl.tsx
@@ -24,7 +24,7 @@ class Repl extends React.Component {
                 if (result.success) {
                     this.executedCommands.push({ command: this.text, result: result.result });
                 } else {
-                    this.executedCommands.push({ command: this.text, result: result.error });
+                    this.executedCommands.push({ command: this.text, result: result.error.message || result.error });
                 }
             }
             this.text = "";
@@ -37,7 +37,7 @@ class Repl extends React.Component {
             return (
                 <div style={{ marginTop: "5px" }}>
                     <p>{command.command}</p>
-                    <p>{JSON.stringify(command.result)}</p>
+                    <pre>{JSON.stringify(command.result, null, 2)}</pre>
                 </div>
             );
         });
-- 
cgit v1.2.3-70-g09d2


From 435f0c8ef035995001dde92f8e7a04fe35a3a41d Mon Sep 17 00:00:00 2001
From: Tyler Schicke <tyler_schicke@brown.edu>
Date: Tue, 28 May 2019 20:00:50 -0400
Subject: Added default values for Document Schemas

---
 src/client/views/nodes/DocumentView.tsx | 13 +++++++------
 src/debug/Repl.tsx                      | 11 ++++++++---
 src/new_fields/Schema.ts                | 18 +++++++++++++++---
 src/new_fields/Types.ts                 | 12 +++++++++---
 4 files changed, 39 insertions(+), 15 deletions(-)

(limited to 'src/debug/Repl.tsx')

diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 01c4d82fb..2fb794925 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -5,7 +5,7 @@ import { observer } from "mobx-react";
 import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc";
 import { List } from "../../../new_fields/List";
 import { ObjectField } from "../../../new_fields/ObjectField";
-import { createSchema, makeInterface } from "../../../new_fields/Schema";
+import { createSchema, makeInterface, defaultSpec } from "../../../new_fields/Schema";
 import { BoolCast, Cast, FieldValue, StrCast } from "../../../new_fields/Types";
 import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils";
 import { emptyFunction, Utils } from "../../../Utils";
@@ -60,15 +60,15 @@ const LinkDoc = makeInterface(linkSchema);
 export interface DocumentViewProps {
     ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
     Document: Doc;
-    addDocument?: (doc: Document, allowDuplicates?: boolean) => boolean;
-    removeDocument?: (doc: Document) => boolean;
-    moveDocument?: (doc: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean;
+    addDocument?: (doc: Doc, allowDuplicates?: boolean) => boolean;
+    removeDocument?: (doc: Doc) => boolean;
+    moveDocument?: (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean;
     ScreenToLocalTransform: () => Transform;
     isTopMost: boolean;
     ContentScaling: () => number;
     PanelWidth: () => number;
     PanelHeight: () => number;
-    focus: (doc: Document) => void;
+    focus: (doc: Doc) => void;
     selectOnLoad: boolean;
     parentActive: () => boolean;
     whenActiveChanged: (isActive: boolean) => void;
@@ -81,7 +81,8 @@ const schema = createSchema({
     layout: "string",
     nativeWidth: "number",
     nativeHeight: "number",
-    backgroundColor: "string"
+    backgroundColor: "string",
+    test: defaultSpec("number", 5)
 });
 
 export const positionSchema = createSchema({
diff --git a/src/debug/Repl.tsx b/src/debug/Repl.tsx
index 01acb0e76..c2db3bdcb 100644
--- a/src/debug/Repl.tsx
+++ b/src/debug/Repl.tsx
@@ -3,6 +3,7 @@ import * as ReactDOM from 'react-dom';
 import { observer } from 'mobx-react';
 import { observable, computed } from 'mobx';
 import { CompileScript } from '../client/util/Scripting';
+import { makeInterface } from '../new_fields/Schema';
 
 @observer
 class Repl extends React.Component {
@@ -15,12 +16,16 @@ class Repl extends React.Component {
     }
 
     onKeyDown = (e: React.KeyboardEvent) => {
-        if (e.ctrlKey && e.key === "Enter") {
-            const script = CompileScript(this.text, { addReturn: true, typecheck: false });
+        if (!e.ctrlKey && e.key === "Enter") {
+            e.preventDefault();
+            const script = CompileScript(this.text, {
+                addReturn: true, typecheck: false,
+                params: { makeInterface: "any" }
+            });
             if (!script.compiled) {
                 this.executedCommands.push({ command: this.text, result: "Compile Error" });
             } else {
-                const result = script.run();
+                const result = script.run({ makeInterface });
                 if (result.success) {
                     this.executedCommands.push({ command: this.text, result: result.result });
                 } else {
diff --git a/src/new_fields/Schema.ts b/src/new_fields/Schema.ts
index b821baec9..250f3c975 100644
--- a/src/new_fields/Schema.ts
+++ b/src/new_fields/Schema.ts
@@ -1,4 +1,4 @@
-import { Interface, ToInterface, Cast, ToConstructor, HasTail, Head, Tail, ListSpec, ToType } from "./Types";
+import { Interface, ToInterface, Cast, ToConstructor, HasTail, Head, Tail, ListSpec, ToType, DefaultFieldConstructor } from "./Types";
 import { Doc, Field } from "./Doc";
 
 type AllToInterface<T extends Interface[]> = {
@@ -10,7 +10,7 @@ export const emptySchema = createSchema({});
 export const Document = makeInterface(emptySchema);
 export type Document = makeInterface<[typeof emptySchema]>;
 
-export type makeInterface<T extends Interface[]> = Partial<AllToInterface<T>> & Doc & { proto: Doc | undefined };
+export type makeInterface<T extends Interface[]> = AllToInterface<T> & Doc & { proto: Doc | undefined };
 // export function makeInterface<T extends Interface[], U extends Doc>(schemas: T): (doc: U) => All<T, U>;
 // export function makeInterface<T extends Interface, U extends Doc>(schema: T): (doc: U) => makeInterface<T, U>; 
 export function makeInterface<T extends Interface[]>(...schemas: T): (doc?: Doc) => makeInterface<T> {
@@ -24,7 +24,12 @@ export function makeInterface<T extends Interface[]>(...schemas: T): (doc?: Doc)
         get(target: any, prop, receiver) {
             const field = receiver.doc[prop];
             if (prop in schema) {
-                return Cast(field, (schema as any)[prop]);
+                const desc = (schema as any)[prop];
+                if (typeof desc === "object" && "defaultVal" in desc && "type" in desc) {
+                    return Cast(field, desc.type, desc.defaultVal);
+                } else {
+                    return Cast(field, (schema as any)[prop]);
+                }
             }
             return field;
         },
@@ -79,4 +84,11 @@ export function createSchema<T extends Interface>(schema: T): T & { proto: ToCon
 
 export function listSpec<U extends ToConstructor<Field>>(type: U): ListSpec<ToType<U>> {
     return { List: type as any };//TODO Types
+}
+
+export function defaultSpec<T extends ToConstructor<Field>>(type: T, defaultVal: ToType<T>): DefaultFieldConstructor<ToType<T>> {
+    return {
+        type: type as any,
+        defaultVal
+    };
 }
\ No newline at end of file
diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts
index 4b4c58eb8..c04dd5e6d 100644
--- a/src/new_fields/Types.ts
+++ b/src/new_fields/Types.ts
@@ -2,12 +2,13 @@ import { Field, Opt, FieldResult, Doc } from "./Doc";
 import { List } from "./List";
 import { RefField } from "./RefField";
 
-export type ToType<T extends ToConstructor<Field> | ListSpec<Field>> =
+export type ToType<T extends ToConstructor<Field> | ListSpec<Field> | DefaultFieldConstructor<Field>> =
     T extends "string" ? string :
     T extends "number" ? number :
     T extends "boolean" ? boolean :
     T extends ListSpec<infer U> ? List<U> :
     // T extends { new(...args: any[]): infer R } ? (R | Promise<R>) : never;
+    T extends DefaultFieldConstructor<infer _U> ? never :
     T extends { new(...args: any[]): List<Field> } ? never :
     T extends { new(...args: any[]): infer R } ? R : never;
 
@@ -19,12 +20,17 @@ export type ToConstructor<T extends Field> =
     new (...args: any[]) => T;
 
 export type ToInterface<T extends Interface> = {
-    [P in Exclude<keyof T, "proto">]: FieldResult<ToType<T[P]>>;
+    [P in Exclude<keyof T, "proto">]: T[P] extends DefaultFieldConstructor<infer F> ? Exclude<FieldResult<F>, undefined> : FieldResult<ToType<T[P]>>;
 };
 
 // type ListSpec<T extends Field[]> = { List: ToContructor<Head<T>> | ListSpec<Tail<T>> };
 export type ListSpec<T extends Field> = { List: ToConstructor<T> };
 
+export type DefaultFieldConstructor<T extends Field> = {
+    type: ToConstructor<T>,
+    defaultVal: T
+};
+
 // type ListType<U extends Field[]> = { 0: List<ListType<Tail<U>>>, 1: ToType<Head<U>> }[HasTail<U> extends true ? 0 : 1];
 
 export type Head<T extends any[]> = T extends [any, ...any[]] ? T[0] : never;
@@ -34,7 +40,7 @@ export type HasTail<T extends any[]> = T extends ([] | [any]) ? false : true;
 
 //TODO Allow you to optionally specify default values for schemas, which should then make that field not be partial
 export interface Interface {
-    [key: string]: ToConstructor<Field> | ListSpec<Field>;
+    [key: string]: ToConstructor<Field> | ListSpec<Field> | DefaultFieldConstructor<Field>;
     // [key: string]: ToConstructor<Field> | ListSpec<Field[]>;
 }
 
-- 
cgit v1.2.3-70-g09d2

