aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTyler Schicke <tyler_schicke@brown.edu>2019-04-24 02:23:36 -0400
committerTyler Schicke <tyler_schicke@brown.edu>2019-04-24 03:21:04 -0400
commit50a950238def89ae30d386676bbfe884c8b8c7be (patch)
treede8b3cf277428db1ab58a9344affc2edc551a9a8 /src
parentf3aef5750b48f375b06540a85b46e404f607c37f (diff)
Added get fields and did some more fixing
Diffstat (limited to 'src')
-rw-r--r--src/client/DocServer.ts25
-rw-r--r--src/client/documents/Documents.ts43
-rw-r--r--src/fields/Document.ts430
-rw-r--r--src/fields/IconFIeld.ts25
-rw-r--r--src/fields/InkField.ts53
-rw-r--r--src/new_fields/IconField.ts14
-rw-r--r--src/new_fields/InkField.ts31
-rw-r--r--src/server/Message.ts1
-rw-r--r--src/server/index.ts6
9 files changed, 101 insertions, 527 deletions
diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index 615e48af0..cba0c4770 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -30,6 +30,31 @@ export namespace DocServer {
}
}
+ export async function GetRefFields(ids: string[]): Promise<{ [id: string]: Opt<RefField> }> {
+ const requestedIds: string[] = [];
+ const waitingIds: string[] = [];
+ const promises: Promise<Opt<RefField>>[] = [];
+ const map: { [id: string]: Opt<RefField> } = {};
+ for (const id of ids) {
+ const cached = _cache[id];
+ if (cached === undefined) {
+ requestedIds.push(id);
+ } else if (cached instanceof Promise) {
+ promises.push(cached);
+ waitingIds.push(id);
+ } else {
+ map[id] = cached;
+ }
+ }
+ const prom = Utils.EmitCallback(_socket, MessageStore.GetFields, requestedIds);
+ requestedIds.map((id, index) => _cache[id] = prom.then((fields: RefField[]) => fields[index]));
+ const fields = await prom;
+ requestedIds.map((id, index) => map[id] = fields[index]);
+ const otherFields = await Promise.all(promises);
+ waitingIds.map((id, index) => map[id] = otherFields[index]);
+ return map;
+ }
+
export function UpdateField(id: string, diff: any) {
Utils.Emit(_socket, MessageStore.UpdateField, { id, diff });
}
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index a145a76c9..a5ce7c076 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -26,6 +26,9 @@ import { ImageField, VideoField, AudioField, PdfField, WebField } from "../../ne
import { HtmlField } from "../../new_fields/HtmlField";
import { List } from "../../new_fields/List";
import { Cast } from "../../new_fields/Types";
+import { IconField } from "../../new_fields/IconField";
+import { listSpec } from "../../new_fields/Schema";
+import { DocServer } from "../DocServer";
export interface DocumentOptions {
x?: number;
@@ -73,17 +76,17 @@ export namespace Docs {
const iconProtoId = "iconProto";
export function initProtos(): Promise<void> {
- return Server.GetFields([textProtoId, histoProtoId, collProtoId, pdfProtoId, imageProtoId, videoProtoId, audioProtoId, webProtoId, kvpProtoId]).then(fields => {
- textProto = fields[textProtoId] as Document || CreateTextPrototype();
- histoProto = fields[histoProtoId] as Document || CreateHistogramPrototype();
- collProto = fields[collProtoId] as Document || CreateCollectionPrototype();
- imageProto = fields[imageProtoId] as Document || CreateImagePrototype();
- webProto = fields[webProtoId] as Document || CreateWebPrototype();
- kvpProto = fields[kvpProtoId] as Document || CreateKVPPrototype();
- videoProto = fields[videoProtoId] as Document || CreateVideoPrototype();
- audioProto = fields[audioProtoId] as Document || CreateAudioPrototype();
- pdfProto = fields[pdfProtoId] as Document || CreatePdfPrototype();
- iconProto = fields[iconProtoId] as Document || CreateIconPrototype();
+ return DocServer.GetRefFields([textProtoId, histoProtoId, collProtoId, pdfProtoId, imageProtoId, videoProtoId, audioProtoId, webProtoId, kvpProtoId]).then(fields => {
+ textProto = fields[textProtoId] as Doc || CreateTextPrototype();
+ histoProto = fields[histoProtoId] as Doc || CreateHistogramPrototype();
+ collProto = fields[collProtoId] as Doc || CreateCollectionPrototype();
+ imageProto = fields[imageProtoId] as Doc || CreateImagePrototype();
+ webProto = fields[webProtoId] as Doc || CreateWebPrototype();
+ kvpProto = fields[kvpProtoId] as Doc || CreateKVPPrototype();
+ videoProto = fields[videoProtoId] as Doc || CreateVideoPrototype();
+ audioProto = fields[audioProtoId] as Doc || CreateAudioPrototype();
+ pdfProto = fields[pdfProtoId] as Doc || CreatePdfPrototype();
+ iconProto = fields[iconProtoId] as Doc || CreateIconPrototype();
});
}
@@ -191,25 +194,29 @@ export namespace Docs {
let ctlog = await Gateway.Instance.GetSchema(url, schemaName);
if (ctlog && ctlog.schemas) {
let schema = ctlog.schemas[0];
- let schemaDoc = Documents.TreeDocument([], { ...options, nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: schema.displayName! });
- let schemaDocuments = schemaDoc.GetList(KeyStore.Data, [] as Document[]);
+ let schemaDoc = Docs.TreeDocument([], { ...options, nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: schema.displayName! });
+ let schemaDocuments = Cast(schemaDoc.data, listSpec(Doc));
+ if (!schemaDocuments) {
+ return;
+ }
+ const docs = schemaDocuments;
CurrentUserUtils.GetAllNorthstarColumnAttributes(schema).map(attr => {
- Server.GetField(attr.displayName! + ".alias", action((field: Opt<Field>) => {
- if (field instanceof Document) {
- schemaDocuments.push(field);
+ DocServer.GetRefField(attr.displayName! + ".alias").then(action((field: Opt<Field>) => {
+ if (field instanceof Doc) {
+ docs.push(field);
} else {
var atmod = new ColumnAttributeModel(attr);
let histoOp = new HistogramOperation(schema.displayName!,
new AttributeTransformationModel(atmod, AggregateFunction.None),
new AttributeTransformationModel(atmod, AggregateFunction.Count),
new AttributeTransformationModel(atmod, AggregateFunction.Count));
- schemaDocuments.push(Documents.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! }, undefined, attr.displayName! + ".alias"));
+ docs.push(Docs.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! }, undefined, attr.displayName! + ".alias"));
}
}));
});
return schemaDoc;
}
- return Documents.TreeDocument([], { width: 50, height: 100, title: schemaName });
+ return Docs.TreeDocument([], { width: 50, height: 100, title: schemaName });
}
export function WebDocument(url: string, options: DocumentOptions = {}) {
return CreateInstance(webProto, new WebField(new URL(url)), options);
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
deleted file mode 100644
index 7cf784f0e..000000000
--- a/src/fields/Document.ts
+++ /dev/null
@@ -1,430 +0,0 @@
-import { Key } from "./Key";
-import { KeyStore } from "./KeyStore";
-import { Field, Cast, FieldWaiting, FieldValue, FieldId, Opt } from "./Field";
-import { NumberField } from "./NumberField";
-import { ObservableMap, computed, action, runInAction } from "mobx";
-import { TextField } from "./TextField";
-import { ListField } from "./ListField";
-import { Server } from "../client/Server";
-import { Types } from "../server/Message";
-import { UndoManager } from "../client/util/UndoManager";
-import { HtmlField } from "./HtmlField";
-import { BooleanField } from "./BooleanField";
-import { allLimit } from "async";
-import { prototype } from "nodemailer/lib/smtp-pool";
-import { HistogramField } from "../client/northstar/dash-fields/HistogramField";
-
-export class Document extends Field {
- //TODO tfs: We should probably store FieldWaiting in fields when we request it from the server so that we don't set up multiple server gets for the same document and field
- public fields: ObservableMap<string, { key: Key; field: Field }> = new ObservableMap();
- public _proxies: ObservableMap<string, FieldId> = new ObservableMap();
-
- constructor(id?: string, save: boolean = true) {
- super(id);
-
- if (save) {
- Server.UpdateField(this);
- }
- }
- static FromJson(data: any, id: string, save: boolean): Document {
- let doc = new Document(id, save);
- let fields = data as [string, string][];
- fields.forEach(pair => doc._proxies.set(pair[0], pair[1]));
- return doc;
- }
-
- UpdateFromServer(data: [string, string][]) {
- for (const key in data) {
- const element = data[key];
- this._proxies.set(element[0], element[1]);
- }
- }
-
- public Width = () => this.GetNumber(KeyStore.Width, 0);
- public Height = () => this.GetNumber(KeyStore.Height, this.GetNumber(KeyStore.NativeWidth, 0) ? (this.GetNumber(KeyStore.NativeHeight, 0) / this.GetNumber(KeyStore.NativeWidth, 0)) * this.GetNumber(KeyStore.Width, 0) : 0);
- public Scale = () => this.GetNumber(KeyStore.Scale, 1);
-
- @computed
- public get Title(): string {
- let title = this.Get(KeyStore.Title, true);
- if (title || title === FieldWaiting) {
- if (title !== FieldWaiting && title instanceof TextField) {
- return title.Data;
- }
- else return "-waiting-";
- }
- let parTitle = this.GetT(KeyStore.Title, TextField);
- if (parTitle || parTitle === FieldWaiting) {
- if (parTitle !== FieldWaiting) return parTitle.Data + ".alias";
- else return "-waiting-.alias";
- }
- return "-untitled-";
- }
-
- @computed
- public get Fields() {
- return this.fields;
- }
-
- /**
- * Get the field in the document associated with the given key. If the
- * associated field has not yet been filled in from the server, a request
- * to the server will automatically be sent, the value will be filled in
- * when the request is completed, and {@link Field.ts#FieldWaiting} will be returned.
- * @param key - The key of the value to get
- * @param ignoreProto - If true, ignore any prototype this document
- * might have and only search for the value on this immediate document.
- * If false (default), search up the prototype chain, starting at this document,
- * for a document that has a field associated with the given key, and return the first
- * one found.
- *
- * @returns If the document does not have a field associated with the given key, returns `undefined`.
- * If the document does have an associated field, but the field has not been fetched from the server, returns {@link Field.ts#FieldWaiting}.
- * If the document does have an associated field, and the field has not been fetched from the server, returns the associated field.
- */
- Get(key: Key, ignoreProto: boolean = false): FieldValue<Field> {
- let field: FieldValue<Field>;
- if (ignoreProto) {
- if (this.fields.has(key.Id)) {
- field = this.fields.get(key.Id)!.field;
- } else if (this._proxies.has(key.Id)) {
- Server.GetDocumentField(this, key);
- /*
- The field might have been instantly filled from the cache
- Maybe we want to just switch back to returning the value
- from Server.GetDocumentField if it's in the cache
- */
- if (this.fields.has(key.Id)) {
- field = this.fields.get(key.Id)!.field;
- } else {
- field = FieldWaiting;
- }
- }
- } else {
- let doc: FieldValue<Document> = this;
- while (doc && field !== FieldWaiting) {
- let curField = doc.fields.get(key.Id);
- let curProxy = doc._proxies.get(key.Id);
- if (!curField || (curProxy && curField.field.Id !== curProxy)) {
- if (curProxy) {
- Server.GetDocumentField(doc, key);
- /*
- The field might have been instantly filled from the cache
- Maybe we want to just switch back to returning the value
- from Server.GetDocumentField if it's in the cache
- */
- if (this.fields.has(key.Id)) {
- field = this.fields.get(key.Id)!.field;
- } else {
- field = FieldWaiting;
- }
- break;
- }
- if (
- doc.fields.has(KeyStore.Prototype.Id) ||
- doc._proxies.has(KeyStore.Prototype.Id)
- ) {
- doc = doc.GetPrototype();
- } else {
- break;
- }
- } else {
- field = curField.field;
- break;
- }
- }
- if (doc === FieldWaiting) field = FieldWaiting;
- }
-
- return field;
- }
-
- /**
- * Tries to get the field associated with the given key, and if there is an
- * associated field, calls the given callback with that field.
- * @param key - The key of the value to get
- * @param callback - A function that will be called with the associated field, if it exists,
- * once it is fetched from the server (this may be immediately if the field has already been fetched).
- * Note: The callback will not be called if there is no associated field.
- * @returns `true` if the field exists on the document and `callback` will be called, and `false` otherwise
- */
- GetAsync(key: Key, callback: (field: Opt<Field>) => void): void {
- //TODO: This currently doesn't deal with prototypes
- let field = this.fields.get(key.Id);
- if (field && field.field) {
- callback(field.field);
- } else if (this._proxies.has(key.Id)) {
- Server.GetDocumentField(this, key, callback);
- } else if (this._proxies.has(KeyStore.Prototype.Id)) {
- this.GetTAsync(KeyStore.Prototype, Document, proto => {
- if (proto) {
- proto.GetAsync(key, callback);
- } else {
- callback(undefined);
- }
- });
- } else {
- callback(undefined);
- }
- }
-
- GetTAsync<T extends Field>(key: Key, ctor: { new(): T }): Promise<Opt<T>>;
- GetTAsync<T extends Field>(
- key: Key,
- ctor: { new(): T },
- callback: (field: Opt<T>) => void
- ): void;
- GetTAsync<T extends Field>(
- key: Key,
- ctor: { new(): T },
- callback?: (field: Opt<T>) => void
- ): Promise<Opt<T>> | void {
- let fn = (cb: (field: Opt<T>) => void) => {
- return this.GetAsync(key, field => {
- cb(Cast(field, ctor));
- });
- };
- if (callback) {
- fn(callback);
- } else {
- return new Promise(fn);
- }
- }
-
- /**
- * Same as {@link Document#GetAsync}, except a field of the given type
- * will be created if there is no field associated with the given key,
- * or the field associated with the given key is not of the given type.
- * @param ctor - Constructor of the field type to get. E.g., TextField, ImageField, etc.
- */
- GetOrCreateAsync<T extends Field>(
- key: Key,
- ctor: { new(): T },
- callback: (field: T) => void
- ): void {
- //This currently doesn't deal with prototypes
- if (this._proxies.has(key.Id)) {
- Server.GetDocumentField(this, key, field => {
- if (field && field instanceof ctor) {
- callback(field);
- } else {
- let newField = new ctor();
- this.Set(key, newField);
- callback(newField);
- }
- });
- } else {
- let newField = new ctor();
- this.Set(key, newField);
- callback(newField);
- }
- }
-
- /**
- * Same as {@link Document#Get}, except that it will additionally
- * check if the field is of the given type.
- * @param ctor - Constructor of the field type to get. E.g., `TextField`, `ImageField`, etc.
- * @returns Same as {@link Document#Get}, except will return `undefined`
- * if there is an associated field but it is of the wrong type.
- */
- GetT<T extends Field = Field>(
- key: Key,
- ctor: { new(...args: any[]): T },
- ignoreProto: boolean = false
- ): FieldValue<T> {
- var getfield = this.Get(key, ignoreProto);
- if (getfield !== FieldWaiting) {
- return Cast(getfield, ctor);
- }
- return FieldWaiting;
- }
-
- GetOrCreate<T extends Field>(
- key: Key,
- ctor: { new(): T },
- ignoreProto: boolean = false
- ): T {
- const field = this.GetT(key, ctor, ignoreProto);
- if (field && field !== FieldWaiting) {
- return field;
- }
- const newField = new ctor();
- this.Set(key, newField);
- return newField;
- }
-
- GetData<T, U extends Field & { Data: T }>(
- key: Key,
- ctor: { new(): U },
- defaultVal: T
- ): T {
- let val = this.Get(key);
- let vval = val && val instanceof ctor ? val.Data : defaultVal;
- return vval;
- }
-
- GetHtml(key: Key, defaultVal: string): string {
- return this.GetData(key, HtmlField, defaultVal);
- }
-
- GetBoolean(key: Key, defaultVal: boolean): boolean {
- return this.GetData(key, BooleanField, defaultVal);
- }
-
- GetNumber(key: Key, defaultVal: number): number {
- return this.GetData(key, NumberField, defaultVal);
- }
-
- GetText(key: Key, defaultVal: string): string {
- return this.GetData(key, TextField, defaultVal);
- }
-
- GetList<T extends Field>(key: Key, defaultVal: T[]): T[] {
- return this.GetData<T[], ListField<T>>(key, ListField, defaultVal);
- }
-
- @action
- Set(key: Key, field: Field | undefined, setOnPrototype = false): void {
- let old = this.fields.get(key.Id);
- let oldField = old ? old.field : undefined;
- if (setOnPrototype) {
- this.SetOnPrototype(key, field);
- } else {
- if (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.Id);
- this._proxies.delete(key.Id);
- // Server.DeleteDocumentField(this, key);
- }
- Server.UpdateField(this);
- }
- if (oldField || field) {
- UndoManager.AddEvent({
- undo: () => this.Set(key, oldField, setOnPrototype),
- redo: () => this.Set(key, field, setOnPrototype)
- });
- }
- }
-
- @action
- SetOnPrototype(key: Key, field: Field | undefined): void {
- this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
- f && f.Set(key, field);
- });
- }
-
- @action
- SetDataOnPrototype<T, U extends Field & { Data: T }>(key: Key, value: T, ctor: { new(): U }, replaceWrongType = true) {
- this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
- f && f.SetData(key, value, ctor, replaceWrongType);
- });
- }
-
- @action
- SetData<T, U extends Field & { Data: T }>(key: Key, value: T, ctor: { new(data: T): U }, replaceWrongType = true) {
- let field = this.Get(key, true);
- if (field instanceof ctor) {
- field.Data = value;
- } else if (!field || replaceWrongType) {
- let newField = new ctor(value);
- // newField.Data = value;
- this.Set(key, newField);
- }
- }
-
- @action
- SetText(key: Key, value: string, replaceWrongType = true) {
- this.SetData(key, value, TextField, replaceWrongType);
- }
- @action
- SetBoolean(key: Key, value: boolean, replaceWrongType = true) {
- this.SetData(key, value, BooleanField, replaceWrongType);
- }
- @action
- SetNumber(key: Key, value: number, replaceWrongType = true) {
- this.SetData(key, value, NumberField, replaceWrongType);
- }
-
- GetPrototype(): FieldValue<Document> {
- return this.GetT(KeyStore.Prototype, Document, true);
- }
-
- GetAllPrototypes(): Document[] {
- let protos: Document[] = [];
- let doc: FieldValue<Document> = this;
- while (doc && doc !== FieldWaiting) {
- protos.push(doc);
- doc = doc.GetPrototype();
- }
- return protos;
- }
-
- CreateAlias(id?: string): Document {
- let alias = new Document(id);
- this.GetTAsync(KeyStore.Prototype, Document, (f: Opt<Document>) => {
- f && alias.Set(KeyStore.Prototype, f);
- });
-
- return alias;
- }
-
- MakeDelegate(id?: string): Document {
- let delegate = new Document(id);
-
- delegate.Set(KeyStore.Prototype, this);
-
- return delegate;
- }
-
- ToScriptString(): string {
- return "";
- }
-
- TrySetValue(value: any): boolean {
- throw new Error("Method not implemented.");
- }
- GetValue() {
- return this.Title;
- var title = (this._proxies.has(KeyStore.Title.Id) ? "???" : this.Title) + "(" + this.Id + ")";
- return title;
- //throw new Error("Method not implemented.");
- }
- Copy(copyProto?: boolean, id?: string): Field {
- let copy = new Document();
- this._proxies.forEach((fieldid, keyid) => { // copy each prototype field
- let key = KeyStore.KeyLookup(keyid);
- if (key) {
- this.GetAsync(key, (field: Opt<Field>) => {
- if (key === KeyStore.Prototype && copyProto) { // handle prototype field specially
- if (field instanceof Document) {
- copy.Set(key, field.Copy(false)); // only copying one level of prototypes for now...
- }
- }
- else
- if (field instanceof Document) { // ... TODO bcz: should we copy documents or reference them
- copy.Set(key!, field);
- }
- else if (field) {
- copy.Set(key!, field.Copy());
- }
- });
- }
- });
- return copy;
- }
-
- ToJson() {
- let fields: [string, string][] = [];
- this._proxies.forEach((field, key) =>
- field && fields.push([key, field]));
-
- return {
- type: Types.Document,
- data: fields,
- id: this.Id
- };
- }
-}
diff --git a/src/fields/IconFIeld.ts b/src/fields/IconFIeld.ts
deleted file mode 100644
index a6694cc49..000000000
--- a/src/fields/IconFIeld.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { BasicField } from "./BasicField";
-import { FieldId } from "./Field";
-import { Types } from "../server/Message";
-
-export class IconField extends BasicField<string> {
- constructor(data: string = "", id?: FieldId, save: boolean = true) {
- super(data, save, id);
- }
-
- ToScriptString(): string {
- return `new IconField("${this.Data}")`;
- }
-
- Copy() {
- return new IconField(this.Data);
- }
-
- ToJson() {
- return {
- type: Types.Icon,
- data: this.Data,
- id: this.Id
- };
- }
-} \ No newline at end of file
diff --git a/src/fields/InkField.ts b/src/fields/InkField.ts
deleted file mode 100644
index 2eacd7d0c..000000000
--- a/src/fields/InkField.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import { BasicField } from "./BasicField";
-import { Types } from "../server/Message";
-import { FieldId } from "./Field";
-import { observable, ObservableMap } from "mobx";
-
-export enum InkTool {
- None,
- Pen,
- Highlighter,
- Eraser
-}
-export interface StrokeData {
- pathData: Array<{ x: number, y: number }>;
- color: string;
- width: string;
- tool: InkTool;
- page: number;
-}
-export type StrokeMap = Map<string, StrokeData>;
-
-export class InkField extends BasicField<StrokeMap> {
- constructor(data: StrokeMap = new Map, id?: FieldId, save: boolean = true) {
- super(data, save, id);
- }
-
- ToScriptString(): string {
- return `new InkField("${this.Data}")`;
- }
-
- Copy() {
- return new InkField(this.Data);
- }
-
- ToJson() {
- return {
- type: Types.Ink,
- data: this.Data,
- id: this.Id,
- };
- }
-
- UpdateFromServer(data: any) {
- this.data = new ObservableMap(data);
- }
-
- static FromJson(id: string, data: any): InkField {
- let map: StrokeMap = new Map<string, StrokeData>();
- Object.keys(data).forEach(key => {
- map.set(key, data[key]);
- });
- return new InkField(map, id, false);
- }
-} \ No newline at end of file
diff --git a/src/new_fields/IconField.ts b/src/new_fields/IconField.ts
new file mode 100644
index 000000000..32f3aa4d5
--- /dev/null
+++ b/src/new_fields/IconField.ts
@@ -0,0 +1,14 @@
+import { Deserializable } from "../client/util/SerializationHelper";
+import { serializable, primitive } from "serializr";
+import { ObjectField } from "./Doc";
+
+@Deserializable("icon")
+export class IconField extends ObjectField {
+ @serializable(primitive())
+ readonly layout: string;
+
+ constructor(layout: string) {
+ super();
+ this.layout = layout;
+ }
+}
diff --git a/src/new_fields/InkField.ts b/src/new_fields/InkField.ts
new file mode 100644
index 000000000..cdb34cedf
--- /dev/null
+++ b/src/new_fields/InkField.ts
@@ -0,0 +1,31 @@
+import { Deserializable } from "../client/util/SerializationHelper";
+import { serializable, custom, createSimpleSchema, list, object, map } from "serializr";
+import { ObjectField } from "./Doc";
+
+export enum InkTool {
+ None,
+ Pen,
+ Highlighter,
+ Eraser
+}
+export interface StrokeData {
+ pathData: Array<{ x: number, y: number }>;
+ color: string;
+ width: string;
+ tool: InkTool;
+ page: number;
+}
+
+const pointSchema = createSimpleSchema({
+ x: true, y: true
+});
+
+const strokeDataSchema = createSimpleSchema({
+ pathData: list(object(pointSchema)),
+ "*": true
+});
+
+export class InkField extends ObjectField {
+ @serializable(map(object(strokeDataSchema)))
+ readonly inkData: Map<string, StrokeData> = new Map;
+}
diff --git a/src/server/Message.ts b/src/server/Message.ts
index b01934724..81da44f72 100644
--- a/src/server/Message.ts
+++ b/src/server/Message.ts
@@ -42,6 +42,7 @@ export namespace MessageStore {
export const DeleteAll = new Message<any>("Delete All");
export const GetRefField = new Message<string>("Get Ref Field");
+ export const GetRefFields = new Message<string[]>("Get Ref Fields");
export const UpdateField = new Message<Diff>("Update Ref Field");
export const CreateField = new Message<Reference>("Create Ref Field");
}
diff --git a/src/server/index.ts b/src/server/index.ts
index d6d5f0e55..10158eb96 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -16,7 +16,6 @@ import { Socket } from 'socket.io';
import * as webpack from 'webpack';
import * as wdm from 'webpack-dev-middleware';
import * as whm from 'webpack-hot-middleware';
-import { Field, FieldId } from '../fields/Field';
import { Utils } from '../Utils';
import { getForgot, getLogin, getLogout, getReset, getSignup, postForgot, postLogin, postReset, postSignup } from './authentication/controllers/user_controller';
import { DashUserModel } from './authentication/models/user_model';
@@ -236,6 +235,7 @@ server.on("connection", function (socket: Socket) {
Utils.AddServerHandler(socket, MessageStore.CreateField, CreateField);
Utils.AddServerHandler(socket, MessageStore.UpdateField, diff => UpdateField(socket, diff));
Utils.AddServerHandler(socket, MessageStore.GetRefField, GetRefField);
+ Utils.AddServerHandler(socket, MessageStore.GetRefFields, GetRefFields);
});
function deleteFields() {
@@ -270,6 +270,10 @@ function GetRefField([id, callback]: [string, (result?: Transferable) => void])
Database.Instance.getDocument(id, callback, "newDocuments");
}
+function GetRefFields([ids, callback]: [string[], (result?: Transferable[]) => void]) {
+ Database.Instance.getDocuments(ids, callback, "newDocuments");
+}
+
function UpdateField(socket: Socket, diff: Diff) {
Database.Instance.update(diff.id, diff.diff,
() => socket.broadcast.emit(MessageStore.UpdateField.Message, diff), false, "newDocuments");