aboutsummaryrefslogtreecommitdiff
path: root/src/fields/List.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/fields/List.ts')
-rw-r--r--src/fields/List.ts97
1 files changed, 47 insertions, 50 deletions
diff --git a/src/fields/List.ts b/src/fields/List.ts
index ec31f7dae..38c47d546 100644
--- a/src/fields/List.ts
+++ b/src/fields/List.ts
@@ -1,31 +1,28 @@
import { action, computed, makeObservable, observable } from 'mobx';
-import { alias, list, serializable } from 'serializr';
-import { DocServer } from '../client/DocServer';
+import { alias, list as serializrList, serializable } from 'serializr';
import { ScriptingGlobals } from '../client/util/ScriptingGlobals';
import { Deserializable, afterDocDeserialize, autoObject } from '../client/util/SerializationHelper';
-import { Field } from './Doc';
+import { Field, FieldType, StrListCast } from './Doc';
import { FieldTuples, Self, SelfProxy } from './DocSymbols';
import { Copy, FieldChanged, Parent, ToJavascriptString, ToScriptString, ToString } from './FieldSymbols';
-import { ObjectField } from './ObjectField';
+import { ObjGetRefFields, ObjectField } from './ObjectField';
import { ProxyField } from './Proxy';
import { RefField } from './RefField';
-import { listSpec } from './Schema';
-import { Cast } from './Types';
import { containedFieldChangedHandler, deleteProperty, getter, setter } from './util';
-function toObjectField(field: Field) {
+function toObjectField(field: FieldType) {
return field instanceof RefField ? new ProxyField(field) : field;
}
-function toRealField(field: Field) {
+function toRealField(field: FieldType) {
return field instanceof ProxyField ? field.value : field;
}
-type StoredType<T extends Field> = T extends RefField ? ProxyField<T> : T;
+type StoredType<T extends FieldType> = T extends RefField ? ProxyField<T> : T;
export const ListFieldName = 'fields';
@Deserializable('list')
-class ListImpl<T extends Field> extends ObjectField {
+class ListImpl<T extends FieldType> extends ObjectField {
static listHandlers: any = {
/// Mutator methods
copyWithin() {
@@ -44,14 +41,14 @@ class ListImpl<T extends Field> extends ObjectField {
this[SelfProxy][FieldChanged]?.();
return field;
},
- push: action(function (this: ListImpl<any>, ...items: any[]) {
- items = items.map(toObjectField);
+ push: action(function (this: ListImpl<any>, ...itemsIn: any[]) {
+ const items = itemsIn.map(toObjectField);
const list = this[Self];
- const length = list.__fieldTuples.length;
+ const { length } = list.__fieldTuples;
for (let i = 0; i < items.length; i++) {
const item = items[i];
- //TODO Error checking to make sure parent doesn't already exist
+ // TODO Error checking to make sure parent doesn't already exist
if (item instanceof ObjectField) {
item[Parent] = list;
item[FieldChanged] = containedFieldChangedHandler(this[SelfProxy], i + length, item);
@@ -77,21 +74,21 @@ class ListImpl<T extends Field> extends ObjectField {
this[SelfProxy][FieldChanged]?.();
return res;
},
- splice: action(function (this: any, start: number, deleteCount: number, ...items: any[]) {
+ splice: action(function (this: any, start: number, deleteCount: number, ...itemsIn: any[]) {
this[Self].__realFields; // coerce retrieving entire array
- items = items.map(toObjectField);
+ const items = itemsIn.map(toObjectField);
const list = this[Self];
const removed = list.__fieldTuples.filter((item: any, i: number) => i >= start && i < start + deleteCount);
for (let i = 0; i < items.length; i++) {
const item = items[i];
- //TODO Error checking to make sure parent doesn't already exist
- //TODO Need to change indices of other fields in array
+ // TODO Error checking to make sure parent doesn't already exist
+ // TODO Need to change indices of other fields in array
if (item instanceof ObjectField) {
item[Parent] = list;
item[FieldChanged] = containedFieldChangedHandler(this, i + start, item);
}
}
- let hintArray: { val: any; index: number }[] = [];
+ const hintArray: { val: any; index: number }[] = [];
for (let i = start; i < start + deleteCount; i++) {
hintArray.push({ val: list.__fieldTuples[i], index: i });
}
@@ -107,13 +104,13 @@ class ListImpl<T extends Field> extends ObjectField {
);
return res.map(toRealField);
}),
- unshift(...items: any[]) {
- items = items.map(toObjectField);
+ unshift(...itemsIn: any[]) {
+ const items = itemsIn.map(toObjectField);
const list = this[Self];
for (let i = 0; i < items.length; i++) {
const item = items[i];
- //TODO Error checking to make sure parent doesn't already exist
- //TODO Need to change indices of other fields in array
+ // TODO Error checking to make sure parent doesn't already exist
+ // TODO Need to change indices of other fields in array
if (item instanceof ObjectField) {
item[Parent] = list;
item[FieldChanged] = containedFieldChangedHandler(this, i, item);
@@ -131,9 +128,8 @@ class ListImpl<T extends Field> extends ObjectField {
includes(valueToFind: any, fromIndex: number) {
if (valueToFind instanceof RefField) {
return this[Self].__realFields.includes(valueToFind, fromIndex);
- } else {
- return this[Self].__fieldTuples.includes(valueToFind, fromIndex);
}
+ return this[Self].__fieldTuples.includes(valueToFind, fromIndex);
},
indexOf(valueToFind: any, fromIndex: number) {
if (valueToFind instanceof RefField) {
@@ -151,9 +147,8 @@ class ListImpl<T extends Field> extends ObjectField {
lastIndexOf(valueToFind: any, fromIndex: number) {
if (valueToFind instanceof RefField) {
return this[Self].__realFields.lastIndexOf(valueToFind, fromIndex);
- } else {
- return this[Self].__fieldTuples.lastIndexOf(valueToFind, fromIndex);
}
+ return this[Self].__fieldTuples.lastIndexOf(valueToFind, fromIndex);
},
slice(begin: number, end: number) {
this[Self].__realFields;
@@ -226,7 +221,7 @@ class ListImpl<T extends Field> extends ObjectField {
},
};
static listGetter(target: any, prop: string | symbol, receiver: any): any {
- if (ListImpl.listHandlers.hasOwnProperty(prop)) {
+ if (Object.prototype.hasOwnProperty.call(ListImpl.listHandlers, prop)) {
return ListImpl.listHandlers[prop];
}
return getter(target, prop, receiver);
@@ -244,7 +239,7 @@ class ListImpl<T extends Field> extends ObjectField {
getOwnPropertyDescriptor: (target, prop) => {
if (prop in target[FieldTuples]) {
return {
- configurable: true, //TODO Should configurable be true?
+ configurable: true, // TODO Should configurable be true?
enumerable: true,
};
}
@@ -255,11 +250,13 @@ class ListImpl<T extends Field> extends ObjectField {
throw new Error("Currently properties can't be defined on documents using Object.defineProperty");
},
});
- this[SelfProxy] = list as any as List<Field>; // bcz: ugh .. don't know how to convince typesecript that list is a List
+ // eslint-disable-next-line no-use-before-define
+ this[SelfProxy] = list as any as List<FieldType>; // bcz: ugh .. don't know how to convince typesecript that list is a List
if (fields) {
this[SelfProxy].push(...fields);
}
- return list;
+ // eslint-disable-next-line no-constructor-return
+ return list; // need to return the proxy here, otherwise we don't get any of our list handler functions
}
[key: number]: T | (T extends RefField ? Promise<T> : never);
@@ -271,7 +268,7 @@ class ListImpl<T extends Field> extends ObjectField {
// if we find any ProxyFields that don't have a current value, then
// start the server request for all of them
if (unrequested.length) {
- const batchPromise = DocServer.GetRefFields(unrequested.map(p => p.fieldId));
+ const batchPromise = ObjGetRefFields(unrequested.map(p => p.fieldId));
// as soon as we get the fields from the server, set all the list values in one
// action to generate one React dom update.
const allSetPromise = batchPromise.then(action(pfields => unrequested.map(toReq => toReq.setValue(pfields[toReq.fieldId]))));
@@ -282,20 +279,20 @@ class ListImpl<T extends Field> extends ObjectField {
return this[FieldTuples].map(toRealField);
}
- @serializable(alias(ListFieldName, list(autoObject(), { afterDeserialize: afterDocDeserialize })))
+ @serializable(alias(ListFieldName, serializrList(autoObject(), { afterDeserialize: afterDocDeserialize })))
private get __fieldTuples() {
return this[FieldTuples];
}
private set __fieldTuples(value) {
this[FieldTuples] = value;
- for (const key in value) {
- const item = value[key];
+ Object.keys(value).forEach(key => {
+ const item = value[Number(key)];
if (item instanceof ObjectField) {
item[Parent] = this[Self];
item[FieldChanged] = containedFieldChangedHandler(this[SelfProxy], Number(key), item);
}
- }
+ });
}
[Copy]() {
@@ -308,24 +305,24 @@ class ListImpl<T extends Field> extends ObjectField {
@observable
private [FieldTuples]: StoredType<T>[] = [];
private [Self] = this;
- private [SelfProxy]: List<Field>; // also used in utils.ts even though it won't be found using find all references
+ // eslint-disable-next-line no-use-before-define
+ private [SelfProxy]: List<FieldType>; // also used in utils.ts even though it won't be found using find all references
- [ToJavascriptString]() {
- return `[${(this as any).map((field: any) => Field.toScriptString(field))}]`;
- }
- [ToScriptString]() {
- return `new List([${(this as any).map((field: any) => Field.toScriptString(field))}])`;
- }
- [ToString]() {
- return `[${(this as any).map((field: any) => Field.toString(field))}]`;
- }
+ [ToScriptString]() { return `new List(${this[ToJavascriptString]()})`; } // prettier-ignore
+ [ToJavascriptString]() { return `[${(this as any).map((field: any) => Field.toScriptString(field))}]`; } // prettier-ignore
+ [ToString]() { return `[${(this as any).map((field: any) => Field.toString(field))}]`; } // prettier-ignore
}
-export type List<T extends Field> = ListImpl<T> & (T | (T extends RefField ? Promise<T> : never))[];
-export const List: { new <T extends Field>(fields?: T[]): List<T> } = ListImpl as any;
+
+// declare List as a type so you can use it in type declarations, e.g., { l: List, ...}
+export type List<T extends FieldType> = ListImpl<T> & (T | (T extends RefField ? Promise<T> : never))[];
+// decalre List as a value so you can invoke 'new' on it, e.g., new List<Doc>()
+// eslint-disable-next-line no-redeclare
+export const List: { new <T extends FieldType>(fields?: T[]): List<T> } = ListImpl as any;
ScriptingGlobals.add('List', List);
+// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function compareLists(l1: any, l2: any) {
- const L1 = Cast(l1, listSpec('string'), []);
- const L2 = Cast(l2, listSpec('string'), []);
+ const L1 = StrListCast(l1);
+ const L2 = StrListCast(l2);
return !L1 && !L2 ? true : L1 && L2 && L1.length === L2.length && L2.reduce((p, v) => p && L1.includes(v), true);
}, 'compare two lists');