aboutsummaryrefslogtreecommitdiff
path: root/src/new_fields/util.ts
diff options
context:
space:
mode:
authorTyler Schicke <tyler_schicke@brown.edu>2019-05-07 16:29:02 -0400
committerTyler Schicke <tyler_schicke@brown.edu>2019-05-07 16:29:02 -0400
commit14c776b6d30e0bc0d5b3712f28e4b9f1170eae3b (patch)
tree5255d8cce8a72a5b09cc1ad58661e2176295467a /src/new_fields/util.ts
parente19fdbba4cf672aee5bfb59b91b6162431d146d3 (diff)
parent26141a697ae52a7edf3cc6845ce2153111f8860e (diff)
Merge branch 'master' of github-tsch-brown:browngraphicslab/Dash-Web into new_search
Diffstat (limited to 'src/new_fields/util.ts')
-rw-r--r--src/new_fields/util.ts104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts
new file mode 100644
index 000000000..bbd8157f6
--- /dev/null
+++ b/src/new_fields/util.ts
@@ -0,0 +1,104 @@
+import { UndoManager } from "../client/util/UndoManager";
+import { Update, Doc, Field } from "./Doc";
+import { SerializationHelper } from "../client/util/SerializationHelper";
+import { ProxyField } from "./Proxy";
+import { FieldValue } from "./Types";
+import { RefField, Id } from "./RefField";
+import { ObjectField, Parent, OnUpdate } from "./ObjectField";
+import { action } from "mobx";
+
+export const setter = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean {
+ if (SerializationHelper.IsSerializing()) {
+ target[prop] = value;
+ return true;
+ }
+ if (typeof prop === "symbol") {
+ target[prop] = value;
+ return true;
+ }
+ const curValue = target.__fields[prop];
+ if (curValue === value || (curValue instanceof ProxyField && value instanceof RefField && curValue.fieldId === value[Id])) {
+ // TODO This kind of checks correctly in the case that curValue is a ProxyField and value is a RefField, but technically
+ // curValue should get filled in with value if it isn't already filled in, in case we fetched the referenced field some other way
+ return true;
+ }
+ if (value instanceof RefField) {
+ value = new ProxyField(value);
+ }
+ if (value instanceof ObjectField) {
+ //TODO Instead of target, maybe use target[Self]
+ if (value[Parent] && value[Parent] !== target) {
+ throw new Error("Can't put the same object in multiple documents at the same time");
+ }
+ value[Parent] = target;
+ value[OnUpdate] = updateFunction(target, prop, value, receiver);
+ }
+ if (curValue instanceof ObjectField) {
+ delete curValue[Parent];
+ delete curValue[OnUpdate];
+ }
+ target.__fields[prop] = value;
+ 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
+ });
+ return true;
+});
+
+export function getter(target: any, prop: string | symbol | number, receiver: any): any {
+ if (typeof prop === "symbol") {
+ return target.__fields[prop] || target[prop];
+ }
+ if (SerializationHelper.IsSerializing()) {
+ return target[prop];
+ }
+ return getField(target, prop);
+}
+
+export function getField(target: any, prop: string | number, ignoreProto: boolean = false, callback?: (field: Field | undefined) => void): any {
+ const field = target.__fields[prop];
+ if (field instanceof ProxyField) {
+ return field.value(callback);
+ }
+ if (field === undefined && !ignoreProto) {
+ const proto = getField(target, "proto", true);
+ if (proto instanceof Doc) {
+ let field = proto[prop];
+ if (field instanceof Promise) {
+ callback && field.then(callback);
+ return undefined;
+ } else {
+ callback && callback(field);
+ return field;
+ }
+ }
+ }
+ callback && callback(field);
+ return field;
+}
+
+export function deleteProperty(target: any, prop: string | number | symbol) {
+ if (typeof prop === "symbol") {
+ delete target[prop];
+ return true;
+ }
+ throw new Error("Currently properties can't be deleted from documents, assign to undefined instead");
+}
+
+export function updateFunction(target: any, prop: any, value: any, receiver: any) {
+ let current = ObjectField.MakeCopy(value);
+ return (diff?: any) => {
+ if (true || !diff) {
+ diff = { '$set': { ["fields." + prop]: SerializationHelper.Serialize(value) } };
+ const oldValue = current;
+ const newValue = ObjectField.MakeCopy(value);
+ current = newValue;
+ UndoManager.AddEvent({
+ redo() { receiver[prop] = newValue; },
+ undo() { receiver[prop] = oldValue; }
+ });
+ }
+ target[Update](diff);
+ };
+} \ No newline at end of file