From 2906c86289825ba92cccc3ccc50434ea4a4326d6 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 6 Jun 2019 21:02:14 -0400 Subject: Added computed fields --- src/new_fields/util.ts | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) (limited to 'src/new_fields/util.ts') diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index 2b304c373..ad07d05a3 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -7,6 +7,7 @@ import { RefField } from "./RefField"; import { ObjectField } from "./ObjectField"; import { action } from "mobx"; import { Parent, OnUpdate, Update, Id } from "./FieldSymbols"; +import { ComputedField } from "../fields/ScriptField"; export const setter = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean { if (SerializationHelper.IsSerializing()) { @@ -60,33 +61,22 @@ export function getter(target: any, prop: string | symbol | number, receiver: an } return getField(target, prop); } -function getProtoField(protoField: Doc | undefined, prop: string | number, cb?: (field: Field | undefined) => void) { - if (!protoField) return undefined; - let field = protoField[prop]; - if (field instanceof Promise) { - cb && field.then(cb); - return field; - } else { - cb && cb(field); - return field; - } -} -//TODO The callback parameter is never being passed in currently, so we should be able to get rid of it. -export function getField(target: any, prop: string | number, ignoreProto: boolean = false, callback?: (field: Field | undefined) => void): any { +export function getField(target: any, prop: string | number, ignoreProto: boolean = false): any { const field = target.__fields[prop]; if (field instanceof ProxyField) { - return field.value(callback); + return field.value(); + } + if (field instanceof ComputedField) { + return field.value; } if (field === undefined && !ignoreProto && prop !== "proto") { const proto = getField(target, "proto", true); if (proto instanceof Doc) { - return getProtoField(proto, prop, callback); - } else if (proto instanceof Promise) { - return proto.then(async proto => getProtoField(proto, prop, callback)); + return proto[prop]; } + return undefined; } - callback && callback(field); return field; } @@ -95,7 +85,8 @@ export function deleteProperty(target: any, prop: string | number | symbol) { delete target[prop]; return true; } - throw new Error("Currently properties can't be deleted from documents, assign to undefined instead"); + target[prop] = undefined; + return true; } export function updateFunction(target: any, prop: any, value: any, receiver: any) { -- cgit v1.2.3-70-g09d2 From 39be491bf3c750902250a0afe0321a05b7643026 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 8 Jun 2019 09:18:46 -0400 Subject: fixed deletion of keys to actually remove them on the server. added '=' syntax on kvp to set on proto. := sets a computed script. =:= sets computed script on proto --- src/client/views/nodes/KeyValueBox.tsx | 49 ++++++++++++++++++++------------- src/client/views/nodes/KeyValuePair.tsx | 20 ++++---------- src/new_fields/util.ts | 3 +- 3 files changed, 37 insertions(+), 35 deletions(-) (limited to 'src/new_fields/util.ts') diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 849f17aa4..917be734d 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -2,13 +2,14 @@ import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app -import { CompileScript } from "../../util/Scripting"; +import { CompileScript, ScriptOptions } from "../../util/Scripting"; import { FieldView, FieldViewProps } from './FieldView'; import "./KeyValueBox.scss"; import { KeyValuePair } from "./KeyValuePair"; import React = require("react"); import { NumCast, Cast, FieldValue } from "../../../new_fields/Types"; import { Doc, Field } from "../../../new_fields/Doc"; +import { ComputedField } from "../../../fields/ScriptField"; @observer export class KeyValueBox extends React.Component { @@ -27,28 +28,38 @@ export class KeyValueBox extends React.Component { @action onEnterKey = (e: React.KeyboardEvent): void => { if (e.key === 'Enter') { - if (this._keyInput && this._valueInput) { - let doc = this.fieldDocToLayout; - if (!doc) { - return; + if (this._keyInput && this._valueInput && this.fieldDocToLayout) { + if (KeyValueBox.SetField(this.fieldDocToLayout, this._keyInput, this._valueInput)) { + this._keyInput = ""; + this._valueInput = ""; } - let realDoc = doc; - - let script = CompileScript(this._valueInput, { addReturn: true }); - if (!script.compiled) { - return; - } - let res = script.run(); - if (!res.success) return; - const field = res.result; - if (Field.IsField(field)) { - realDoc[this._keyInput] = field; - } - this._keyInput = ""; - this._valueInput = ""; } } } + public static SetField(doc: Doc, key: string, value: string) { + let eq = value.startsWith("="); + value = eq ? value.substr(1) : value; + let dubEq = value.startsWith(":="); + value = dubEq ? value.substr(2) : value; + let options: ScriptOptions = { addReturn: true }; + if (dubEq) options.typecheck = false; + let script = CompileScript(value, options); + if (!script.compiled) { + return false; + } + let field = new ComputedField(script); + if (!dubEq) { + let res = script.run(); + if (!res.success) return false; + field = res.result; + } + if (Field.IsField(field, true)) { + let target = !eq ? doc : Doc.GetProto(doc); + target[key] = field; + return true; + } + return false; + } onPointerDown = (e: React.PointerEvent): void => { if (e.buttons === 1 && this.props.isSelected()) { diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 228d07018..e8bc17532 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -2,7 +2,7 @@ import { action, observable } from 'mobx'; import { observer } from "mobx-react"; import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app import { emptyFunction, returnFalse, returnZero, returnTrue } from '../../../Utils'; -import { CompileScript } from "../../util/Scripting"; +import { CompileScript, CompiledScript, ScriptOptions } from "../../util/Scripting"; import { Transform } from '../../util/Transform'; import { EditableView } from "../EditableView"; import { FieldView, FieldViewProps } from './FieldView'; @@ -11,6 +11,8 @@ import "./KeyValuePair.scss"; import React = require("react"); import { Doc, Opt, Field } from '../../../new_fields/Doc'; import { FieldValue } from '../../../new_fields/Types'; +import { ComputedField } from '../../../fields/ScriptField'; +import { KeyValueBox } from './KeyValueBox'; // Represents one row in a key value plane @@ -66,20 +68,8 @@ export class KeyValuePair extends React.Component { } return ""; }} - SetValue={(value: string) => { - let script = CompileScript(value, { addReturn: true }); - if (!script.compiled) { - return false; - } - let res = script.run(); - if (!res.success) return false; - const field = res.result; - if (Field.IsField(field, true)) { - props.Document[props.fieldKey] = field; - return true; - } - return false; - }}> + SetValue={(value: string) => + KeyValueBox.SetField(props.Document, props.fieldKey, value)}> ); diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index ad07d05a3..fe0da2e7a 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -44,7 +44,8 @@ export const setter = action(function (target: any, prop: string | symbol | numb } else { target.__fields[prop] = value; } - target[Update]({ '$set': { ["fields." + prop]: value instanceof ObjectField ? SerializationHelper.Serialize(value) : (value === undefined ? null : value) } }); + if (value === undefined) target[Update]({ '$unset': { ["fields." + prop]: "" } }); + else target[Update]({ '$set': { ["fields." + prop]: value instanceof ObjectField ? SerializationHelper.Serialize(value) : (value === undefined ? null : value) } }); UndoManager.AddEvent({ redo: () => receiver[prop] = value, undo: () => receiver[prop] = curValue -- cgit v1.2.3-70-g09d2