diff options
Diffstat (limited to 'src/fields')
| -rw-r--r-- | src/fields/BasicField.ts | 18 | ||||
| -rw-r--r-- | src/fields/Document.ts | 64 | ||||
| -rw-r--r-- | src/fields/DocumentReference.ts | 6 | ||||
| -rw-r--r-- | src/fields/Field.ts | 17 | ||||
| -rw-r--r-- | src/fields/ImageField.ts | 6 | ||||
| -rw-r--r-- | src/fields/Key.ts | 35 | ||||
| -rw-r--r-- | src/fields/KeyStore.ts | 24 | ||||
| -rw-r--r-- | src/fields/ListField.ts | 65 | ||||
| -rw-r--r-- | src/fields/NumberField.ts | 7 | ||||
| -rw-r--r-- | src/fields/RichTextField.ts | 7 | ||||
| -rw-r--r-- | src/fields/TextField.ts | 7 |
11 files changed, 175 insertions, 81 deletions
diff --git a/src/fields/BasicField.ts b/src/fields/BasicField.ts index 9476f5d21..15eb067a0 100644 --- a/src/fields/BasicField.ts +++ b/src/fields/BasicField.ts @@ -3,14 +3,23 @@ import { observable, computed, action } from "mobx"; import { Server } from "../client/Server"; export abstract class BasicField<T> extends Field { - constructor(data: T, id: FIELD_ID = undefined) { + constructor(data: T, save: boolean, id: FIELD_ID = undefined) { super(id); this.data = data; + if (save) { + Server.UpdateField(this) + } + } + + UpdateFromServer(data: any) { + if (this.data !== data) { + this.data = data; + } } @observable - private data: T; + protected data: T; @computed get Data(): T { @@ -18,10 +27,9 @@ export abstract class BasicField<T> extends Field { } set Data(value: T) { - if (this.data === value) { - return; + if (this.data != value) { + this.data = value; } - this.data = value; Server.UpdateField(this); } diff --git a/src/fields/Document.ts b/src/fields/Document.ts index f7239145f..3067621be 100644 --- a/src/fields/Document.ts +++ b/src/fields/Document.ts @@ -1,19 +1,34 @@ import { Field, Cast, Opt, FieldWaiting, FIELD_ID, FieldValue } from "./Field" -import { Key, KeyStore } from "./Key" +import { Key } from "./Key" +import { KeyStore } from "./KeyStore"; import { NumberField } from "./NumberField"; import { ObservableMap, computed, action, observable } from "mobx"; import { TextField } from "./TextField"; import { ListField } from "./ListField"; -import { findDOMNode } from "react-dom"; import { Server } from "../client/Server"; import { Types } from "../server/Message"; -import { ObjectID } from "bson"; -import { Utils } from "../Utils"; export class Document extends Field { - public fields: ObservableMap<Key, Opt<Field>> = new ObservableMap(); + public fields: ObservableMap<string, { key: Key, field: Field }> = new ObservableMap(); public _proxies: ObservableMap<string, FIELD_ID> = new ObservableMap(); + constructor(id?: string, save: boolean = true) { + super(id) + + if (save) { + var title = (this._proxies.has(KeyStore.Title.Id) ? "???" : this.Title) + "(" + this.Id + ")"; + console.log("Save " + title); + Server.UpdateField(this) + } + } + + UpdateFromServer(data: [string, string][]) { + for (const key in data) { + const element = data[key]; + this._proxies.set(element[0], element[1]); + } + } + @computed public get Title() { return this.GetText(KeyStore.Title, "<untitled>"); @@ -22,28 +37,33 @@ export class Document extends Field { Get(key: Key, ignoreProto: boolean = false): FieldValue<Field> { let field: FieldValue<Field>; if (ignoreProto) { - if (this.fields.has(key)) { - field = this.fields.get(key); + if (this.fields.has(key.Id)) { + field = this.fields.get(key.Id)!.field; } else if (this._proxies.has(key.Id)) { field = Server.GetDocumentField(this, key); } } else { let doc: FieldValue<Document> = this; while (doc && doc != FieldWaiting && field != FieldWaiting) { - if (!doc.fields.has(key)) { - if (doc._proxies.has(key.Id)) { + let curField = doc.fields.get(key.Id); + let curProxy = doc._proxies.get(key.Id); + if (!curField || (curProxy && curField.field.Id !== curProxy)) { + if (curProxy) { field = Server.GetDocumentField(doc, key); break; } - if ((doc.fields.has(KeyStore.Prototype) || doc._proxies.has(KeyStore.Prototype.Id))) { + if ((doc.fields.has(KeyStore.Prototype.Id) || doc._proxies.has(KeyStore.Prototype.Id))) { doc = doc.GetPrototype(); - } else + } else { break; + } } else { - field = doc.fields.get(key); + field = curField.field; break; } } + if (doc == FieldWaiting) + field = FieldWaiting; } return field; @@ -87,11 +107,14 @@ export class Document extends Field { @action Set(key: Key, field: Field | undefined): void { + console.log("Assign: " + key.Name + " = " + (field ? field.GetValue() : "<undefined>") + " (" + (field ? field.Id : "<undefined>") + ")"); if (field) { - this.fields.set(key, field); + this.fields.set(key.Id, { key, field }); + this._proxies.set(key.Id, field.Id) // Server.AddDocumentField(this, key, field); } else { - this.fields.delete(key); + this.fields.delete(key.Id); + this._proxies.delete(key.Id) // Server.DeleteDocumentField(this, key); } Server.UpdateField(this); @@ -137,8 +160,8 @@ export class Document extends Field { return protos; } - MakeDelegate(): Document { - let delegate = new Document(); + MakeDelegate(id?: string): Document { + let delegate = new Document(id); delegate.Set(KeyStore.Prototype, this); @@ -153,19 +176,23 @@ export class Document extends Field { throw new Error("Method not implemented."); } GetValue() { - throw new Error("Method not implemented."); + var title = (this._proxies.has(KeyStore.Title.Id) ? "???" : this.Title) + "(" + this.Id + ")"; + return title; + //throw new Error("Method not implemented."); } Copy(): Field { throw new Error("Method not implemented."); } - ToJson(): { type: Types, data: [string, string][], _id: String } { + ToJson(): { type: Types, data: [string, string][], _id: string } { + // console.log(this.fields) let fields: [string, string][] = [] this._proxies.forEach((field, key) => { if (field) { fields.push([key, field as string]) } }); + // console.log(fields) return { type: Types.Document, @@ -173,5 +200,4 @@ export class Document extends Field { _id: this.Id } } - }
\ No newline at end of file diff --git a/src/fields/DocumentReference.ts b/src/fields/DocumentReference.ts index c9313a73e..4096cbb92 100644 --- a/src/fields/DocumentReference.ts +++ b/src/fields/DocumentReference.ts @@ -17,6 +17,10 @@ export class DocumentReference extends Field { super(); } + UpdateFromServer() { + + } + Dereference(): FieldValue<Field> { return this.document.Get(this.key); } @@ -43,7 +47,7 @@ export class DocumentReference extends Field { return ""; } - ToJson(): { type: Types, data: FIELD_ID, _id: String } { + ToJson(): { type: Types, data: FIELD_ID, _id: string } { return { type: Types.DocumentReference, data: this.document.Id, diff --git a/src/fields/Field.ts b/src/fields/Field.ts index 16569e175..853fb9327 100644 --- a/src/fields/Field.ts +++ b/src/fields/Field.ts @@ -1,15 +1,6 @@ import { Utils } from "../Utils"; import { Types } from "../server/Message"; -import { NumberField } from "./NumberField"; -import { TextField } from "./TextField"; -import { RichTextField } from "./RichTextField"; -import { KeyStore, Key } from "./Key"; -import { ImageField } from "./ImageField"; -import { ListField } from "./ListField"; -import { Document } from "./Document"; -import { Server } from "../client/Server"; -import { ObjectID } from "bson"; export function Cast<T extends Field>(field: FieldValue<Field>, ctor: { new(): T }): Opt<T> { if (field) { @@ -29,6 +20,10 @@ export type FieldValue<T> = Opt<T> | FIELD_WAITING; export abstract class Field { //FieldUpdated: TypedEvent<Opt<FieldUpdatedArgs>> = new TypedEvent<Opt<FieldUpdatedArgs>>(); + init(callback: (res: Field) => any) { + callback(this); + } + private id: string; get Id(): string { return this.id; @@ -57,6 +52,8 @@ export abstract class Field { return this.id === other.id; } + abstract UpdateFromServer(serverData: any): void; + abstract ToScriptString(): string; abstract TrySetValue(value: any): boolean; @@ -65,5 +62,5 @@ export abstract class Field { abstract Copy(): Field; - abstract ToJson(): { _id: String, type: Types, data: any } + abstract ToJson(): { _id: string, type: Types, data: any } }
\ No newline at end of file diff --git a/src/fields/ImageField.ts b/src/fields/ImageField.ts index 39eed9398..aba011199 100644 --- a/src/fields/ImageField.ts +++ b/src/fields/ImageField.ts @@ -4,8 +4,8 @@ import { Types } from "../server/Message"; import { ObjectID } from "bson"; export class ImageField extends BasicField<URL> { - constructor(data: URL | undefined = undefined, id: FIELD_ID = undefined) { - super(data == undefined ? new URL("http://cs.brown.edu/~bcz/bob_fettucine.jpg") : data, id); + constructor(data: URL | undefined = undefined, id: FIELD_ID = undefined, save: boolean = true) { + super(data == undefined ? new URL("http://cs.brown.edu/~bcz/bob_fettucine.jpg") : data, save, id); } toString(): string { @@ -20,7 +20,7 @@ export class ImageField extends BasicField<URL> { return new ImageField(this.Data); } - ToJson(): { type: Types, data: URL, _id: String } { + ToJson(): { type: Types, data: URL, _id: string } { return { type: Types.Image, data: this.Data, diff --git a/src/fields/Key.ts b/src/fields/Key.ts index 7120c6e3e..d3958df2d 100644 --- a/src/fields/Key.ts +++ b/src/fields/Key.ts @@ -3,6 +3,7 @@ import { Utils } from "../Utils"; import { observable } from "mobx"; import { Types } from "../server/Message"; import { ObjectID } from "bson"; +import { Server } from "../client/Server"; export class Key extends Field { private name: string; @@ -11,10 +12,17 @@ export class Key extends Field { return this.name; } - constructor(name: string, id?: string) { + constructor(name: string, id?: string, save: boolean = true) { super(id || Utils.GenerateDeterministicGuid(name)); this.name = name; + if (save) { + Server.UpdateField(this) + } + } + + UpdateFromServer(data: string) { + this.name = data; } TrySetValue(value: any): boolean { @@ -33,34 +41,11 @@ export class Key extends Field { return name; } - ToJson(): { type: Types, data: string, _id: String } { + ToJson(): { type: Types, data: string, _id: string } { return { type: Types.Key, data: this.name, _id: this.Id } } -} - -export namespace KeyStore { - export const Prototype = new Key("Prototype"); - export const X = new Key("X"); - export const Y = new Key("Y"); - export const Title = new Key("Title"); - export const Author = new Key("Author"); - export const PanX = new Key("PanX"); - export const PanY = new Key("PanY"); - export const Scale = new Key("Scale"); - export const Width = new Key("Width"); - export const Height = new Key("Height"); - export const ZIndex = new Key("ZIndex"); - export const Data = new Key("Data"); - export const Layout = new Key("Layout"); - export const LayoutKeys = new Key("LayoutKeys"); - export const LayoutFields = new Key("LayoutFields"); - export const ColumnsKey = new Key("SchemaColumns"); - - export function Get(name: string): Key { - return new Key(name) - } }
\ No newline at end of file diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts new file mode 100644 index 000000000..1e0b12729 --- /dev/null +++ b/src/fields/KeyStore.ts @@ -0,0 +1,24 @@ +import { Key } from "./Key"; + +export namespace KeyStore { + export const Prototype = new Key("Prototype"); + export const X = new Key("X"); + export const Y = new Key("Y"); + export const Title = new Key("Title"); + export const Author = new Key("Author"); + export const PanX = new Key("PanX"); + export const PanY = new Key("PanY"); + export const Scale = new Key("Scale"); + export const Width = new Key("Width"); + export const Height = new Key("Height"); + export const ZIndex = new Key("ZIndex"); + export const Data = new Key("Data"); + export const Layout = new Key("Layout"); + export const LayoutKeys = new Key("LayoutKeys"); + export const LayoutFields = new Key("LayoutFields"); + export const ColumnsKey = new Key("SchemaColumns"); + + export function Get(name: string): Key { + return new Key(name) + } +} diff --git a/src/fields/ListField.ts b/src/fields/ListField.ts index 9a26cb142..1357dc445 100644 --- a/src/fields/ListField.ts +++ b/src/fields/ListField.ts @@ -1,11 +1,58 @@ -import { Field, FIELD_ID } from "./Field"; +import { Field, FIELD_ID, FieldValue, Opt } from "./Field"; import { BasicField } from "./BasicField"; import { Types } from "../server/Message"; -import { ObjectId } from "bson"; +import { observe, action } from "mobx"; +import { Server } from "../client/Server"; +import { ServerUtils } from "../server/ServerUtil"; export class ListField<T extends Field> extends BasicField<T[]> { - constructor(data: T[] = [], id: FIELD_ID = undefined) { - super(data.slice(), id); + private _proxies: string[] = [] + constructor(data: T[] = [], id: FIELD_ID = undefined, save: boolean = true) { + super(data, save, id); + this.updateProxies(); + if (save) { + Server.UpdateField(this); + } + observe(this.Data, () => { + this.updateProxies() + Server.UpdateField(this); + }) + } + + private updateProxies() { + this._proxies = this.Data.map(field => field.Id); + } + + UpdateFromServer(fields: string[]) { + this._proxies = fields; + } + private arraysEqual(a: any[], b: any[]) { + if (a === b) return true; + if (a == null || b == null) return false; + if (a.length != b.length) return false; + + // If you don't care about the order of the elements inside + // the array, you should sort both arrays here. + // Please note that calling sort on an array will modify that array. + // you might want to clone your array first. + + for (var i = 0; i < a.length; ++i) { + if (a[i] !== b[i]) return false; + } + return true; + } + + init(callback: (field: Field) => any) { + Server.GetFields(this._proxies, action((fields: { [index: string]: Field }) => { + if (!this.arraysEqual(this._proxies, this.Data.map(field => field.Id))) { + this.data = this._proxies.map(id => fields[id] as T) + observe(this.Data, () => { + this.updateProxies() + Server.UpdateField(this); + }) + } + callback(this); + })) } ToScriptString(): string { @@ -16,11 +63,17 @@ export class ListField<T extends Field> extends BasicField<T[]> { return new ListField<T>(this.Data); } - ToJson(): { type: Types, data: T[], _id: String } { + ToJson(): { type: Types, data: string[], _id: string } { return { type: Types.List, - data: this.Data, + data: this._proxies, _id: this.Id } } + + static FromJson(id: string, ids: string[]): ListField<Field> { + let list = new ListField([], id, false); + list._proxies = ids; + return list + } }
\ No newline at end of file diff --git a/src/fields/NumberField.ts b/src/fields/NumberField.ts index f31be0c25..29e285201 100644 --- a/src/fields/NumberField.ts +++ b/src/fields/NumberField.ts @@ -1,11 +1,10 @@ import { BasicField } from "./BasicField" import { Types } from "../server/Message"; import { FIELD_ID } from "./Field"; -import { ObjectID } from "bson"; export class NumberField extends BasicField<number> { - constructor(data: number = 0, id: FIELD_ID = undefined) { - super(data, id); + constructor(data: number = 0, id: FIELD_ID = undefined, save: boolean = true) { + super(data, save, id); } ToScriptString(): string { @@ -16,7 +15,7 @@ export class NumberField extends BasicField<number> { return new NumberField(this.Data); } - ToJson(): { _id: String, type: Types, data: number } { + ToJson(): { _id: string, type: Types, data: number } { return { _id: this.Id, type: Types.Number, diff --git a/src/fields/RichTextField.ts b/src/fields/RichTextField.ts index 2ed4d11f8..9783107e3 100644 --- a/src/fields/RichTextField.ts +++ b/src/fields/RichTextField.ts @@ -1,11 +1,10 @@ import { BasicField } from "./BasicField"; import { Types } from "../server/Message"; import { FIELD_ID } from "./Field"; -import { ObjectID } from "bson"; export class RichTextField extends BasicField<string> { - constructor(data: string = "", id: FIELD_ID = undefined) { - super(data, id); + constructor(data: string = "", id: FIELD_ID = undefined, save: boolean = true) { + super(data, save, id); } ToScriptString(): string { @@ -16,7 +15,7 @@ export class RichTextField extends BasicField<string> { return new RichTextField(this.Data); } - ToJson(): { type: Types, data: string, _id: String } { + ToJson(): { type: Types, data: string, _id: string } { return { type: Types.RichText, data: this.Data, diff --git a/src/fields/TextField.ts b/src/fields/TextField.ts index 545aa8c35..efb3c035f 100644 --- a/src/fields/TextField.ts +++ b/src/fields/TextField.ts @@ -1,11 +1,10 @@ import { BasicField } from "./BasicField" import { FIELD_ID } from "./Field"; import { Types } from "../server/Message"; -import { ObjectID } from "bson"; export class TextField extends BasicField<string> { - constructor(data: string = "", id: FIELD_ID = undefined) { - super(data, id); + constructor(data: string = "", id: FIELD_ID = undefined, save: boolean = true) { + super(data, save, id); } ToScriptString(): string { @@ -16,7 +15,7 @@ export class TextField extends BasicField<string> { return new TextField(this.Data); } - ToJson(): { type: Types, data: string, _id: String } { + ToJson(): { type: Types, data: string, _id: string } { return { type: Types.Text, data: this.Data, |
