From 404dcc71558d8de69369aa499227e5168091351d Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Wed, 5 Jun 2019 22:42:43 -0400 Subject: Can now pass list to schema function to get list of that type Mapped type of a schema can be another schema Added tests for schemas Other minor fixes --- src/new_fields/Schema.ts | 34 +++++++++++++++++++++++++++++----- src/new_fields/Types.ts | 8 +++++--- 2 files changed, 34 insertions(+), 8 deletions(-) (limited to 'src/new_fields') diff --git a/src/new_fields/Schema.ts b/src/new_fields/Schema.ts index 250f3c975..40ffaecd5 100644 --- a/src/new_fields/Schema.ts +++ b/src/new_fields/Schema.ts @@ -1,5 +1,7 @@ import { Interface, ToInterface, Cast, ToConstructor, HasTail, Head, Tail, ListSpec, ToType, DefaultFieldConstructor } from "./Types"; import { Doc, Field } from "./Doc"; +import { ObjectField } from "./ObjectField"; +import { RefField } from "./RefField"; type AllToInterface = { 1: ToInterface> & AllToInterface>, @@ -10,10 +12,16 @@ export const emptySchema = createSchema({}); export const Document = makeInterface(emptySchema); export type Document = makeInterface<[typeof emptySchema]>; +export interface InterfaceFunc { + (docs: Doc[]): makeInterface[]; + (): makeInterface; + (doc: Doc): makeInterface; +} + export type makeInterface = AllToInterface & Doc & { proto: Doc | undefined }; // export function makeInterface(schemas: T): (doc: U) => All; // export function makeInterface(schema: T): (doc: U) => makeInterface; -export function makeInterface(...schemas: T): (doc?: Doc) => makeInterface { +export function makeInterface(...schemas: T): InterfaceFunc { let schema: Interface = {}; for (const s of schemas) { for (const key in s) { @@ -25,10 +33,19 @@ export function makeInterface(...schemas: T): (doc?: Doc) const field = receiver.doc[prop]; if (prop in schema) { const desc = (schema as any)[prop]; - if (typeof desc === "object" && "defaultVal" in desc && "type" in desc) { + if (typeof desc === "object" && "defaultVal" in desc && "type" in desc) {//defaultSpec return Cast(field, desc.type, desc.defaultVal); + } else if (typeof desc === "function" && !ObjectField.isPrototypeOf(desc) && !RefField.isPrototypeOf(desc)) { + const doc = Cast(field, Doc); + if (doc === undefined) { + return undefined; + } else if (doc instanceof Doc) { + return desc(doc); + } else { + return doc.then(doc => doc && desc(doc)); + } } else { - return Cast(field, (schema as any)[prop]); + return Cast(field, desc); } } return field; @@ -38,14 +55,21 @@ export function makeInterface(...schemas: T): (doc?: Doc) return true; } }); - return function (doc?: Doc) { - doc = doc || new Doc; + const fn = (doc: Doc) => { if (!(doc instanceof Doc)) { throw new Error("Currently wrapping a schema in another schema isn't supported"); } const obj = Object.create(proto, { doc: { value: doc, writable: false } }); return obj; }; + return function (doc?: Doc | Doc[]) { + doc = doc || new Doc; + if (doc instanceof Doc) { + return fn(doc); + } else { + return doc.map(fn); + } + }; } export type makeStrictInterface = Partial>; diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts index c04dd5e6d..8dd893aa4 100644 --- a/src/new_fields/Types.ts +++ b/src/new_fields/Types.ts @@ -2,7 +2,7 @@ import { Field, Opt, FieldResult, Doc } from "./Doc"; import { List } from "./List"; import { RefField } from "./RefField"; -export type ToType | ListSpec | DefaultFieldConstructor> = +export type ToType = T extends "string" ? string : T extends "number" ? number : T extends "boolean" ? boolean : @@ -10,7 +10,8 @@ export type ToType | ListSpec | DefaultFie // T extends { new(...args: any[]): infer R } ? (R | Promise) : never; T extends DefaultFieldConstructor ? never : T extends { new(...args: any[]): List } ? never : - T extends { new(...args: any[]): infer R } ? R : never; + T extends { new(...args: any[]): infer R } ? R : + T extends (doc?: Doc) => infer R ? R : never; export type ToConstructor = T extends string ? "string" : @@ -38,9 +39,10 @@ export type Tail = ((...t: T) => any) extends ((_: any, ...tail: infer TT) => any) ? TT : []; export type HasTail = T extends ([] | [any]) ? false : true; +export type InterfaceValue = ToConstructor | ListSpec | DefaultFieldConstructor | ((doc?: Doc) => any); //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 | ListSpec | DefaultFieldConstructor; + [key: string]: InterfaceValue; // [key: string]: ToConstructor | ListSpec; } -- cgit v1.2.3-70-g09d2 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/client/util/Scripting.ts | 3 +- src/client/util/SerializationHelper.ts | 14 ++- src/client/util/type_decls.d | 49 ++++++---- src/debug/Repl.tsx | 5 +- src/fields/ScriptField.ts | 174 ++++++++++++++++----------------- src/new_fields/util.ts | 29 ++---- 6 files changed, 140 insertions(+), 134 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index beaf5cb03..40e2ad6bb 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -12,6 +12,7 @@ import { Doc, Field } from '../../new_fields/Doc'; import { ImageField, PdfField, VideoField, AudioField } from '../../new_fields/URLField'; import { List } from '../../new_fields/List'; import { RichTextField } from '../../new_fields/RichTextField'; +import { ScriptField, ComputedField } from '../../fields/ScriptField'; export interface ScriptSucccess { success: true; @@ -45,7 +46,7 @@ function Run(script: string | undefined, customParams: string[], diagnostics: an return { compiled: false, errors: diagnostics }; } - let fieldTypes = [Doc, ImageField, PdfField, VideoField, AudioField, List, RichTextField]; + let fieldTypes = [Doc, ImageField, PdfField, VideoField, AudioField, List, RichTextField, ScriptField, ComputedField, CompileScript]; let paramNames = ["Docs", ...fieldTypes.map(fn => fn.name)]; let params: any[] = [Docs, ...fieldTypes]; let compiledFunction = new Function(...paramNames, `return ${script}`); diff --git a/src/client/util/SerializationHelper.ts b/src/client/util/SerializationHelper.ts index 7ded85e43..a7246d7c4 100644 --- a/src/client/util/SerializationHelper.ts +++ b/src/client/util/SerializationHelper.ts @@ -45,13 +45,17 @@ export namespace SerializationHelper { throw Error(`type '${obj.__type}' not registered. Make sure you register it using a @Deserializable decorator`); } - const value = deserialize(serializationTypes[obj.__type], obj); + const type = serializationTypes[obj.__type]; + const value = deserialize(type.ctor, obj); + if (type.afterDeserialize) { + type.afterDeserialize(value); + } serializing -= 1; return value; } } -let serializationTypes: { [name: string]: any } = {}; +let serializationTypes: { [name: string]: { ctor: { new(): any }, afterDeserialize?: (obj: any) => void } } = {}; let reverseMap: { [ctor: string]: string } = {}; export interface DeserializableOpts { @@ -59,9 +63,9 @@ export interface DeserializableOpts { withFields(fields: string[]): Function; } -export function Deserializable(name: string): DeserializableOpts; +export function Deserializable(name: string, afterDeserialize?: (obj: any) => void): DeserializableOpts; export function Deserializable(constructor: { new(...args: any[]): any }): void; -export function Deserializable(constructor: { new(...args: any[]): any } | string): DeserializableOpts | void { +export function Deserializable(constructor: { new(...args: any[]): any } | string, afterDeserialize?: (obj: any) => void): DeserializableOpts | void { function addToMap(name: string, ctor: { new(...args: any[]): any }) { const schema = getDefaultModelSchema(ctor) as any; if (schema.targetClass !== ctor) { @@ -69,7 +73,7 @@ export function Deserializable(constructor: { new(...args: any[]): any } | strin setDefaultModelSchema(ctor, newSchema); } if (!(name in serializationTypes)) { - serializationTypes[name] = ctor; + serializationTypes[name] = { ctor, afterDeserialize }; reverseMap[ctor.name] = name; } else { throw new Error(`Name ${name} has already been registered as deserializable`); diff --git a/src/client/util/type_decls.d b/src/client/util/type_decls.d index 557f6f574..b3c049d02 100644 --- a/src/client/util/type_decls.d +++ b/src/client/util/type_decls.d @@ -141,17 +141,12 @@ declare abstract class RefField { readonly [Id]: FieldId; constructor(); - // protected [HandleUpdate]?(diff: any): void; - - // abstract [ToScriptString](): string; } -declare abstract class ObjectField { - protected [OnUpdate](diff?: any): void; - private [Parent]?: RefField | ObjectField; - // abstract [Copy](): ObjectField; +declare type FieldId = string; - // abstract [ToScriptString](): string; +declare abstract class ObjectField { + abstract [Copy](): ObjectField; } declare abstract class URLField extends ObjectField { @@ -161,32 +156,48 @@ declare abstract class URLField extends ObjectField { constructor(url: URL); } -declare class AudioField extends URLField { } -declare class VideoField extends URLField { } -declare class ImageField extends URLField { } -declare class WebField extends URLField { } -declare class PdfField extends URLField { } - -declare type FieldId = string; +declare class AudioField extends URLField { [Copy](): ObjectField; } +declare class VideoField extends URLField { [Copy](): ObjectField; } +declare class ImageField extends URLField { [Copy](): ObjectField; } +declare class WebField extends URLField { [Copy](): ObjectField; } +declare class PdfField extends URLField { [Copy](): ObjectField; } +// @ts-ignore +declare type Extract = T extends U ? T : never; declare type Field = number | string | boolean | ObjectField | RefField; +declare type FieldWaiting = T extends undefined ? never : Promise; +declare type FieldResult = Opt | FieldWaiting>; declare type Opt = T | undefined; declare class Doc extends RefField { constructor(); - [key: string]: Field | undefined; + [key: string]: FieldResult; // [ToScriptString](): string; } declare class ListImpl extends ObjectField { constructor(fields?: T[]); [index: number]: T | (T extends RefField ? Promise : never); - // [ToScriptString](): string; - // [Copy](): ObjectField; + [Copy](): ObjectField; } // @ts-ignore declare const console: any; -declare const Documents: any; +interface DocumentOptions { } + +declare const Docs: { + ImageDocument(url: string, options?: DocumentOptions): Doc; + VideoDocument(url: string, options?: DocumentOptions): Doc; + // HistogramDocument(url:string, options?:DocumentOptions); + TextDocument(options?: DocumentOptions): Doc; + PdfDocument(url: string, options?: DocumentOptions): Doc; + WebDocument(url: string, options?: DocumentOptions): Doc; + HtmlDocument(html: string, options?: DocumentOptions): Doc; + KVPDocument(document: Doc, options?: DocumentOptions): Doc; + FreeformDocument(documents: Doc[], options?: DocumentOptions): Doc; + SchemaDocument(columns: string[], documents: Doc[], options?: DocumentOptions): Doc; + TreeDocument(documents: Doc[], options?: DocumentOptions): Doc; + StackingDocument(documents: Doc[], options?: DocumentOptions): Doc; +}; diff --git a/src/debug/Repl.tsx b/src/debug/Repl.tsx index c2db3bdcb..91b711c79 100644 --- a/src/debug/Repl.tsx +++ b/src/debug/Repl.tsx @@ -4,6 +4,8 @@ import { observer } from 'mobx-react'; import { observable, computed } from 'mobx'; import { CompileScript } from '../client/util/Scripting'; import { makeInterface } from '../new_fields/Schema'; +import { ObjectField } from '../new_fields/ObjectField'; +import { RefField } from '../new_fields/RefField'; @observer class Repl extends React.Component { @@ -42,7 +44,8 @@ class Repl extends React.Component { return (

{command.command}

-
{JSON.stringify(command.result, null, 2)}
+ {/*
{JSON.stringify(command.result, null, 2)}
*/} +
{command.result instanceof RefField || command.result instanceof ObjectField ? "object" : String(command.result)}
); }); diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index ae532c9e2..05ed57ea5 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -1,101 +1,97 @@ -// import { Field, FieldId } from "./Field"; -// import { Types } from "../server/Message"; -// import { CompileScript, ScriptOptions, CompiledScript } from "../client/util/Scripting"; -// import { Server } from "../client/Server"; -// import { Without } from "../Utils"; +import { ObjectField } from "../new_fields/ObjectField"; +import { CompiledScript, CompileScript } from "../client/util/Scripting"; +import { Copy, ToScriptString, Parent, SelfProxy } from "../new_fields/FieldSymbols"; +import { serializable, createSimpleSchema, map, primitive, object, deserialize, PropSchema, custom, SKIP } from "serializr"; +import { Deserializable } from "../client/util/SerializationHelper"; +import { computed } from "mobx"; -// export interface SerializableOptions extends Without { -// capturedIds: { [id: string]: string }; -// } +function optional(propSchema: PropSchema) { + return custom(value => { + if (value !== undefined) { + return propSchema.serializer(value); + } + return SKIP; + }, (jsonValue: any, context: any, oldValue: any, callback: (err: any, result: any) => void) => { + if (jsonValue !== undefined) { + return propSchema.deserializer(jsonValue, callback, context, oldValue); + } + return SKIP; + }); +} -// export interface ScriptData { -// script: string; -// options: SerializableOptions; -// } +const optionsSchema = createSimpleSchema({ + requiredType: true, + addReturn: true, + typecheck: true, + params: optional(map(primitive())) +}); -// export class ScriptField extends Field { -// private _script?: CompiledScript; -// get script(): CompiledScript { -// return this._script!; -// } -// private options?: ScriptData; +function deserializeScript(script: ScriptField) { + const comp = CompileScript(script.scriptString, script.options); + if (!comp.compiled) { + throw new Error("Couldn't compile loaded script"); + } + (script as any)._script = comp; +} -// constructor(script?: CompiledScript, id?: FieldId, save: boolean = true) { -// super(id); +@Deserializable("script", deserializeScript) +export class ScriptField extends ObjectField { + protected readonly _script: CompiledScript; -// this._script = script; + constructor(script: CompiledScript) { + super(); -// if (save) { -// Server.UpdateField(this); -// } -// } + this._script = script; + } -// ToScriptString() { -// return "new ScriptField(...)"; -// } + @serializable(object(optionsSchema)) + get options() { + return this._script.options; + } -// GetValue() { -// return this.script; -// } + @serializable(true) + get scriptString(): string { + return this._script.originalScript; + } -// TrySetValue(): boolean { -// throw new Error("Script fields currently can't be modified"); -// } + // init(callback: (res: Field) => any) { + // const options = this.options!; + // const keys = Object.keys(options.options.capturedIds); + // Server.GetFields(keys).then(fields => { + // let captured: { [name: string]: Field } = {}; + // keys.forEach(key => captured[options.options.capturedIds[key]] = fields[key]); + // const opts: ScriptOptions = { + // addReturn: options.options.addReturn, + // params: options.options.params, + // requiredType: options.options.requiredType, + // capturedVariables: captured + // }; + // const script = CompileScript(options.script, opts); + // if (!script.compiled) { + // throw new Error("Can't compile script"); + // } + // this._script = script; + // callback(this); + // }); + // } -// UpdateFromServer() { -// throw new Error("Script fields currently can't be updated"); -// } + [Copy](): ObjectField { + return new ScriptField(this._script); + } -// static FromJson(id: string, data: ScriptData): ScriptField { -// let field = new ScriptField(undefined, id, false); -// field.options = data; -// return field; -// } + [ToScriptString]() { + return "script field"; + } +} -// init(callback: (res: Field) => any) { -// const options = this.options!; -// const keys = Object.keys(options.options.capturedIds); -// Server.GetFields(keys).then(fields => { -// let captured: { [name: string]: Field } = {}; -// keys.forEach(key => captured[options.options.capturedIds[key]] = fields[key]); -// const opts: ScriptOptions = { -// addReturn: options.options.addReturn, -// params: options.options.params, -// requiredType: options.options.requiredType, -// capturedVariables: captured -// }; -// const script = CompileScript(options.script, opts); -// if (!script.compiled) { -// throw new Error("Can't compile script"); -// } -// this._script = script; -// callback(this); -// }); -// } - -// ToJson() { -// const { options, originalScript } = this.script; -// let capturedIds: { [id: string]: string } = {}; -// for (const capt in options.capturedVariables) { -// capturedIds[options.capturedVariables[capt].Id] = capt; -// } -// const opts: SerializableOptions = { -// ...options, -// capturedIds -// }; -// delete (opts as any).capturedVariables; -// return { -// id: this.Id, -// type: Types.Script, -// data: { -// script: originalScript, -// options: opts, -// }, -// }; -// } - -// Copy(): Field { -// //Script fields are currently immutable, so we can fake copy them -// return this; -// } -// } \ No newline at end of file +@Deserializable("computed") +export class ComputedField extends ScriptField { + @computed + get value() { + const val = this._script.run({ this: (this[Parent] as any)[SelfProxy] }); + if (val.success) { + return val.result; + } + return undefined; + } +} \ No newline at end of file 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 e1b7feda380f540e677e69e306d91d6b57ce03e7 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 7 Jun 2019 19:42:43 -0400 Subject: tree view reordering. --- src/client/documents/Documents.ts | 2 +- src/client/util/DragManager.ts | 16 +++-- .../views/collections/CollectionDockingView.tsx | 5 +- .../views/collections/CollectionStackingView.tsx | 1 - src/client/views/collections/CollectionSubView.tsx | 24 ++----- .../views/collections/CollectionTreeView.scss | 79 ++++++++++++---------- src/new_fields/Doc.ts | 6 +- .../authentication/models/current_user_utils.ts | 1 + 8 files changed, 70 insertions(+), 64 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ab61b915c..5f2d729cf 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -30,7 +30,7 @@ import { Cast, NumCast } from "../../new_fields/Types"; import { IconField } from "../../new_fields/IconField"; import { listSpec } from "../../new_fields/Schema"; import { DocServer } from "../DocServer"; -import { StrokeData, InkField } from "../../new_fields/InkField"; +import { InkField } from "../../new_fields/InkField"; import { dropActionType } from "../util/DragManager"; import { DateField } from "../../new_fields/DateField"; import { UndoManager } from "../util/UndoManager"; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 1e84a0db0..32476b785 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -6,7 +6,7 @@ import { CollectionDockingView } from "../views/collections/CollectionDockingVie import * as globalCssVariables from "../views/globalCssVariables.scss"; export type dropActionType = "alias" | "copy" | undefined; -export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc | Promise, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType) { +export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc | Promise, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType, options?: any, dontHideOnDrop?: boolean) { let onRowMove = async (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); @@ -16,6 +16,8 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () var dragData = new DragManager.DocumentDragData([await docFunc()]); dragData.dropAction = dropAction; dragData.moveDocument = moveFunc; + dragData.options = options; + dragData.dontHideOnDrop = dontHideOnDrop; DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y); }; let onRowUp = (): void => { @@ -185,6 +187,7 @@ export namespace DragManager { export let AbortDrag: () => void = emptyFunction; function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: { [id: string]: any }) => void) { + eles = eles.filter(e => e); if (!dragDiv) { dragDiv = document.createElement("div"); dragDiv.className = "dragManager-dragDiv"; @@ -241,6 +244,13 @@ export namespace DragManager { // pdfBox.replaceChild(img, pdfBox.children[0]) // } // } + let set = dragElement.getElementsByTagName('*'); + for (let i = 0; i < set.length; i++) + if (set[i].hasAttribute("style")) { + let s = set[i]; + (s as any).style.pointerEvents = "none"; + } + dragDiv.appendChild(dragElement); return dragElement; @@ -259,8 +269,6 @@ export namespace DragManager { let lastX = downX; let lastY = downY; const moveHandler = (e: PointerEvent) => { - e.stopPropagation(); - e.preventDefault(); if (dragData instanceof DocumentDragData) { dragData.userDropAction = e.ctrlKey || e.altKey ? "alias" : undefined; } @@ -309,7 +317,7 @@ export namespace DragManager { } function dispatchDrag(dragEles: HTMLElement[], e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions, finishDrag?: (dragData: { [index: string]: any }) => void) { - let removed = dragEles.map(dragEle => { + let removed = dragData.dontHideOnDrop ? [] : dragEles.map(dragEle => { // let parent = dragEle.parentElement; // if (parent) parent.removeChild(dragEle); let ret = [dragEle, dragEle.style.width, dragEle.style.height]; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 8f6c9b1fc..51e29cb54 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -23,6 +23,7 @@ import "./CollectionDockingView.scss"; import { SubCollectionViewProps } from "./CollectionSubView"; import { ParentDocSelector } from './ParentDocumentSelector'; import React = require("react"); +import { MainView } from '../MainView'; @observer export class CollectionDockingView extends React.Component { @@ -457,7 +458,9 @@ export class DockedFrameRenderer extends React.Component { get previewPanelCenteringOffset() { return (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2; } addDocTab = (doc: Doc, location: string) => { - if (location === "onRight") { + if (doc.dockingConfig) { + MainView.Instance.openWorkspace(doc); + } else if (location === "onRight") { CollectionDockingView.Instance.AddRightSplit(doc); } else { CollectionDockingView.Instance.AddTab(this._stack, doc); diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index b8eb4ac84..0a119a3b4 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -109,7 +109,6 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } @computed get children() { - trace(); return this.childDocs.filter(d => !d.isMinimized).map((d, i) => { let dref = React.createRef(); let dxf = () => this.getDocTransform(d, dref.current!); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 06d77fec5..762955a08 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -18,6 +18,7 @@ import { CollectionVideoView } from "./CollectionVideoView"; import { CollectionView } from "./CollectionView"; import React = require("react"); import { FormattedTextBox } from "../nodes/FormattedTextBox"; +import { Id } from "../../../new_fields/FieldSymbols"; export interface CollectionViewProps extends FieldViewProps { addDocument: (document: Doc, allowDuplicates?: boolean) => boolean; @@ -81,28 +82,15 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { @action protected drop(e: Event, de: DragManager.DropEvent): boolean { if (de.data instanceof DragManager.DocumentDragData) { - if (de.data.dropAction || de.data.userDropAction) { - ["width", "height", "curPage"].map(key => - de.data.draggedDocuments.map((draggedDocument: Doc, i: number) => - PromiseValue(Cast(draggedDocument[key], "number")).then(f => f && (de.data.droppedDocuments[i][key] = f)))); - } let added = false; if (de.data.dropAction || de.data.userDropAction) { - added = de.data.droppedDocuments.reduce((added: boolean, d) => { - let moved = this.props.addDocument(d); - return moved || added; - }, false); + added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false); } else if (de.data.moveDocument) { - const move = de.data.moveDocument; - added = de.data.droppedDocuments.reduce((added: boolean, d) => { - let moved = move(d, this.props.Document, this.props.addDocument); - return moved || added; - }, false); + let movedDocs = de.data.options === this.props.Document[Id] ? de.data.draggedDocuments : de.data.droppedDocuments; + added = movedDocs.reduce((added: boolean, d) => + de.data.moveDocument(d, this.props.Document, this.props.addDocument) || added, false); } else { - added = de.data.droppedDocuments.reduce((added: boolean, d) => { - let moved = this.props.addDocument(d); - return moved || added; - }, false); + added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false); } e.stopPropagation(); return added; diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index 458030b28..2dc4b2e80 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -19,10 +19,6 @@ padding-left: 20px; } - li { - margin: 5px 0; - } - .no-indent { padding-left: 0; @@ -34,30 +30,9 @@ width: 15px; display: block; color: $intermediate-color; - margin-top: 3px; + margin-top: 8px; transform: scale(1.3, 1.3); } - - .docContainer { - margin-left: 10px; - display: block; - // width:100%;//width: max-content; - } - - .docContainer:hover { - .treeViewItem-openRight { - display: inline-block; - height:13px; - // display: inline; - svg { - display:block; - padding:0px; - margin: 0px; - } - } - } - - .editableView-container { font-weight: bold; } @@ -70,10 +45,6 @@ display: inline; } - .treeViewItem-openRight { - margin-left: 5px; - display: none; - } .docContainer:hover { .delete-button { @@ -88,13 +59,51 @@ font-size: 24px; } - .collection-child { - margin-top: 10px; - margin-bottom: 10px; - } - .collectionTreeView-keyHeader { font-style: italic; font-size: 8pt; } +} + +.docContainer { + margin-left: 10px; + display: block; + // width:100%;//width: max-content; + + .treeViewItem-openRight { + margin-left: 5px; + display: none; + } +} +#docContainer-data { + margin-top: 5px; +} + +.docContainer:hover { + .treeViewItem-openRight { + display: inline-block; + height:13px; + // display: inline; + svg { + display:block; + padding:0px; + margin: 0px; + } + } +} + +.treeViewItem-header { + border: transparent 1px solid; +} +.treeViewItem-header-above { + border: transparent 1px solid; + border-top: black 1px solid; +} +.treeViewItem-header-below { + border: transparent 1px solid; + border-bottom: black 1px solid; +} +.treeViewItem-header-inside { + border: transparent 1px solid; + border: black 1px solid; } \ No newline at end of file diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 7f7263cf1..7e02a5bc5 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -211,13 +211,11 @@ export namespace Doc { return Array.from(results); } - export function MakeAlias(doc: Doc) { - const alias = new Doc; if (!GetT(doc, "isPrototype", "boolean", true)) { - alias.proto = doc.proto; + return Doc.MakeCopy(doc); } - return alias; + return new Doc; } export function MakeCopy(doc: Doc, copyProto: boolean = false): Doc { diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index e5b7a025b..816c5f269 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -29,6 +29,7 @@ export class CurrentUserUtils { private static createUserDocument(id: string): Doc { let doc = new Doc(id, true); doc.viewType = CollectionViewType.Tree; + doc.dropAction = "alias"; doc.layout = CollectionView.LayoutString(); doc.title = this.email; doc.data = new List(); -- 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') 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 From c56851026c4054cde26ea36a9a24db14fac6c49c Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 10 Jun 2019 13:03:47 -0400 Subject: fixes for treeview highlighting, templates, field deletion, overlaytext box positioning --- src/Utils.ts | 2 +- src/client/util/DragManager.ts | 6 ++++-- src/client/util/SelectionManager.ts | 9 +++++--- src/client/views/MainOverlayTextBox.tsx | 8 +++++--- src/client/views/Templates.tsx | 16 ++++----------- .../views/collections/CollectionTreeView.tsx | 24 ++++++++++++++-------- .../collectionFreeForm/CollectionFreeFormView.tsx | 3 +-- src/client/views/nodes/DocumentView.tsx | 6 +++--- src/new_fields/util.ts | 4 ++-- 9 files changed, 42 insertions(+), 36 deletions(-) (limited to 'src/new_fields') diff --git a/src/Utils.ts b/src/Utils.ts index 611c61135..e8a80bdc3 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -15,7 +15,7 @@ export class Utils { return v5(seed, v5.URL); } - public static GetScreenTransform(ele: HTMLElement): { scale: number, translateX: number, translateY: number } { + public static GetScreenTransform(ele?: HTMLElement): { scale: number, translateX: number, translateY: number } { if (!ele) { return { scale: 1, translateX: 1, translateY: 1 }; } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 4c9f798a8..8ee1ad2af 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,9 +1,10 @@ -import { action, runInAction } from "mobx"; +import { action, runInAction, observable } from "mobx"; import { Doc, DocListCastAsync } from "../../new_fields/Doc"; import { Cast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import * as globalCssVariables from "../views/globalCssVariables.scss"; +import { SelectionManager } from "./SelectionManager"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc | Promise, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType, options?: any, dontHideOnDrop?: boolean) { @@ -194,7 +195,7 @@ export namespace DragManager { dragDiv.style.pointerEvents = "none"; DragManager.Root().appendChild(dragDiv); } - + SelectionManager.SetIsDragging(true); let scaleXs: number[] = []; let scaleYs: number[] = []; let xs: number[] = []; @@ -293,6 +294,7 @@ export namespace DragManager { }; let hideDragElements = () => { + SelectionManager.SetIsDragging(false); dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement)); eles.map(ele => (ele.hidden = false)); }; diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 0e22d576c..ddad4b818 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -1,4 +1,4 @@ -import { observable, action } from "mobx"; +import { observable, action, runInAction } from "mobx"; import { Doc } from "../../new_fields/Doc"; import { DocumentView } from "../views/nodes/DocumentView"; import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; @@ -6,8 +6,8 @@ import { NumCast } from "../../new_fields/Types"; export namespace SelectionManager { class Manager { - @observable - SelectedDocuments: Array = []; + @observable IsDragging: boolean = false; + @observable SelectedDocuments: Array = []; @action SelectDoc(doc: DocumentView, ctrlPressed: boolean): void { @@ -51,6 +51,9 @@ export namespace SelectionManager { if (found) manager.SelectDoc(found, false); } + export function SetIsDragging(dragging: boolean) { runInAction(() => manager.IsDragging = dragging); } + export function GetIsDragging() { return manager.IsDragging; } + export function SelectedDocuments(): Array { return manager.SelectedDocuments; } diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index 6bbd70a25..0eb3e9707 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -1,7 +1,7 @@ import { action, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { emptyFunction, returnTrue, returnZero } from '../../Utils'; +import { emptyFunction, returnTrue, returnZero, Utils } from '../../Utils'; import { DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; import "normalize.css"; @@ -29,7 +29,8 @@ export class MainOverlayTextBox extends React.Component MainOverlayTextBox.Instance = this; reaction(() => FormattedTextBox.InputBoxOverlay, (box?: FormattedTextBox) => { - if (box) this.setTextDoc(box.props.fieldKey, box.CurrentDiv, box.props.ScreenToLocalTransform); + let sxf = Utils.GetScreenTransform(box ? box.CurrentDiv : undefined); + if (box) this.setTextDoc(box.props.fieldKey, box.CurrentDiv, () => new Transform(-sxf.translateX, -sxf.translateY, 1 / sxf.scale)); else this.setTextDoc(); }); } @@ -93,9 +94,10 @@ export class MainOverlayTextBox extends React.Component if (FormattedTextBox.InputBoxOverlay && this._textTargetDiv) { let textRect = this._textTargetDiv.getBoundingClientRect(); let s = this._textXf().Scale; + let auto = FormattedTextBox.InputBoxOverlay.props.height; return
+ style={{ width: `${textRect.width * s}px`, height: auto ? "auto" : `${textRect.height * s}px` }}> diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx index 8943bbcaf..3cd525afa 100644 --- a/src/client/views/Templates.tsx +++ b/src/client/views/Templates.tsx @@ -41,21 +41,13 @@ export namespace Templates { export const Caption = new Template("Caption", TemplatePosition.OutterBottom, `
-
{layout}
+
{layout}
- +
` ); - export const ImageTitle = new Template("Image Title", TemplatePosition.InnerTop, - `
-
{layout}
-
- {props.Document.title} -
-
` ); - - export const TextTitle = new Template("Text Title", TemplatePosition.InnerTop, + export const Title = new Template("Title", TemplatePosition.InnerTop, `
{props.Document.title} @@ -92,7 +84,7 @@ export namespace Templates {
`); } - export const TemplateList: Template[] = [TextTitle, Header, ImageTitle, Caption, Bullet]; + export const TemplateList: Template[] = [Title, Header, Caption, Bullet]; export function sortTemplates(a: Template, b: Template) { if (a.Position < b.Position) { return -1; } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 8dc10bcd1..8a6764c58 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -20,6 +20,7 @@ import { CollectionSubView } from "./CollectionSubView"; import "./CollectionTreeView.scss"; import React = require("react"); import { Transform } from '../../util/Transform'; +import { SelectionManager } from '../../util/SelectionManager'; export interface TreeViewProps { @@ -32,6 +33,7 @@ export interface TreeViewProps { ScreenToLocalTransform: () => Transform; treeViewId: string; parentKey: string; + active: () => boolean; } export enum BulletType { @@ -69,7 +71,7 @@ class TreeView extends React.Component { @action onMouseLeave = () => { this._isOver = false; } onPointerEnter = (e: React.PointerEvent): void => { - this.props.document.libraryBrush = true; + this.props.active() && (this.props.document.libraryBrush = true); if (e.buttons === 1) { this._header!.current!.className = "treeViewItem-header"; document.addEventListener("pointermove", this.onDragMove, true); @@ -149,7 +151,10 @@ class TreeView extends React.Component {
); return (
{editableView(StrCast(this.props.document.title))} {openRight} @@ -225,18 +230,19 @@ class TreeView extends React.Component { while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1); } keys.map(key => { - let docList = DocListCast(this.props.document[key]); + let docList = Cast(this.props.document[key], listSpec(Doc)); let remDoc = (doc: Doc) => this.remove(doc, key); let addDoc = (doc: Doc, addBefore?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.document, key, doc, addBefore, before); let doc = Cast(this.props.document[key], Doc); - if (doc instanceof Doc || docList.length) { + if (doc instanceof Doc || docList) { if (!this._collapsed) { bulletType = BulletType.Collapsible; contentElement.push(
    {(key === "data") ? (null) : {key}}
    - {TreeView.GetChildElements(doc instanceof Doc ? [doc] : docList, this.props.treeViewId, key, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform)} + {TreeView.GetChildElements(doc instanceof Doc ? [doc] : DocListCast(docList), this.props.treeViewId, key, addDoc, remDoc, this.move, + this.props.dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.active)}
); } else { @@ -266,11 +272,12 @@ class TreeView extends React.Component { move: DragManager.MoveFunction, dropAction: dropActionType, addDocTab: (doc: Doc, where: string) => void, - screenToLocalXf: () => Transform + screenToLocalXf: () => Transform, + active: () => boolean ) { return docs.filter(child => !child.excludeFromLibrary && (key !== "data" || !child.isMinimized)).map(child => ); + dropAction={dropAction} addDocTab={addDocTab} ScreenToLocalTransform={screenToLocalXf} parentKey={key} active={active} />); } } @@ -309,7 +316,8 @@ export class CollectionTreeView extends CollectionSubView(Document) { } let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => TreeView.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before); let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); - let childElements = TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.fieldKey, addDoc, this.remove, moveDoc, dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform); + let childElements = TreeView.GetChildElements(this.childDocs, this.props.Document[Id], this.props.fieldKey, addDoc, this.remove, + moveDoc, dropAction, this.props.addDocTab, this.props.ScreenToLocalTransform, this.props.active); return (
(Docu dst.nativeHeight = src.nativeHeight; } else { - const docs = await SearchUtil.Search(`data_l:"${destDoc[Id]}"`, true); - const views = docs.map(d => DocumentManager.Instance.getDocumentView(d)).filter(d => d).map(d => d as DocumentView); - DocUtils.MakeLink(sourceDoc, destDoc, views.length ? views[0].props.Document : undefined); + // const docs = await SearchUtil.Search(`data_l:"${destDoc[Id]}"`, true); + // const views = docs.map(d => DocumentManager.Instance.getDocumentView(d)).filter(d => d).map(d => d as DocumentView); + DocUtils.MakeLink(sourceDoc, destDoc, this.props.ContainingCollectionView ? this.props.ContainingCollectionView.props.Document : undefined); de.data.droppedDocuments.push(destDoc); } } diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index fe0da2e7a..8cb1db953 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -6,7 +6,7 @@ import { FieldValue } from "./Types"; import { RefField } from "./RefField"; import { ObjectField } from "./ObjectField"; import { action } from "mobx"; -import { Parent, OnUpdate, Update, Id } from "./FieldSymbols"; +import { Parent, OnUpdate, Update, Id, SelfProxy } from "./FieldSymbols"; import { ComputedField } from "../fields/ScriptField"; export const setter = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean { @@ -86,7 +86,7 @@ export function deleteProperty(target: any, prop: string | number | symbol) { delete target[prop]; return true; } - target[prop] = undefined; + target[SelfProxy][prop] = undefined; return true; } -- cgit v1.2.3-70-g09d2