diff options
author | srichman333 <sarah_n_richman@brown.edu> | 2023-06-14 17:23:23 -0400 |
---|---|---|
committer | srichman333 <sarah_n_richman@brown.edu> | 2023-06-14 17:23:23 -0400 |
commit | f0474c18d092f4db49255a1e92d7f052b7398897 (patch) | |
tree | 1e26ccaf42dec4d99904e2eddb36dff6f3b55948 /src/fields/util.ts | |
parent | 20d217d825891cf29a432a048d1f8e7bc04d062a (diff) | |
parent | bf1198fbe73847087b1ec8e00a43306816b3508a (diff) |
Merge branch 'master' into collaboration-sarah
Diffstat (limited to 'src/fields/util.ts')
-rw-r--r-- | src/fields/util.ts | 112 |
1 files changed, 52 insertions, 60 deletions
diff --git a/src/fields/util.ts b/src/fields/util.ts index 5e925cd7e..6058a5a5f 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -9,11 +9,10 @@ import { returnZero } from '../Utils'; import CursorField from './CursorField'; import { AclAdmin, - AclAugment, AclEdit, aclLevel, AclPrivate, - AclReadonly, + AclSelfEdit, AclSym, DataSym, Doc, @@ -35,7 +34,7 @@ import { ObjectField } from './ObjectField'; import { PrefetchProxy, ProxyField } from './Proxy'; import { RefField } from './RefField'; import { SchemaHeaderField } from './SchemaHeaderField'; -import { ComputedField } from './ScriptField'; +import { ComputedField, ScriptField } from './ScriptField'; import { ScriptCast, StrCast } from './Types'; import { convertCompilerOptionsFromJson } from 'typescript'; @@ -57,7 +56,7 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number if (value !== undefined) { value = value[SelfProxy] || value; } - const curValue = target.__fields[prop]; + const curValue = target.__fieldTuples[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 @@ -66,6 +65,7 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number if (value instanceof RefField) { value = new ProxyField(value); } + if (value instanceof ObjectField) { if (value[Parent] && value[Parent] !== receiver && !(value instanceof PrefetchProxy)) { throw new Error("Can't put the same object in multiple documents at the same time"); @@ -88,11 +88,13 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number if (writeToDoc) { if (value === undefined) { - target.__fieldKeys && delete target.__fieldKeys[prop]; - delete target.__fields[prop]; + target[FieldKeys] && delete target[FieldKeys][prop]; // Lists don't have a FieldKeys field + delete target.__fieldTuples[prop]; } else { - target.__fieldKeys && (target.__fieldKeys[prop] = true); - target.__fields[prop] = value; + // bcz: uncomment to see if server is being updated + // console.log(prop + ' = ' + value + '(' + curValue + ')'); + target[FieldKeys] && (target[FieldKeys][prop] = true); // Lists don't have a FieldKeys field + target.__fieldTuples[prop] = value; } if (writeToServer) { @@ -103,20 +105,24 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number DocServer.registerDocWithCachedUpdate(receiver, prop as string, curValue); } !receiver[Initializing] && + !receiver.dontUndo && (!receiver[UpdatingFromServer] || receiver[ForceServerWrite]) && - UndoManager.AddEvent({ - redo: () => (receiver[prop] = value), - undo: () => { - const wasUpdate = receiver[UpdatingFromServer]; - const wasForce = receiver[ForceServerWrite]; - receiver[ForceServerWrite] = true; // needed since writes aren't propagated to server if UpdatingFromServerIsSet - receiver[UpdatingFromServer] = true; // needed if the event caused ACL's to change such that the doc is otherwise no longer editable. - receiver[prop] = curValue; - receiver[ForceServerWrite] = wasForce; - receiver[UpdatingFromServer] = wasUpdate; + UndoManager.AddEvent( + { + redo: () => (receiver[prop] = value), + undo: () => { + const wasUpdate = receiver[UpdatingFromServer]; + const wasForce = receiver[ForceServerWrite]; + receiver[ForceServerWrite] = true; // needed since writes aren't propagated to server if UpdatingFromServerIsSet + receiver[UpdatingFromServer] = true; // needed if the event caused ACL's to change such that the doc is otherwise no longer editable. + receiver[prop] = curValue; + receiver[ForceServerWrite] = wasForce; + receiver[UpdatingFromServer] = wasUpdate; + }, + prop: prop?.toString(), }, - prop: prop?.toString(), - }); + value + ); return true; } return false; @@ -143,13 +149,13 @@ export function denormalizeEmail(email: string) { * Copies parent's acl fields to the child */ export function inheritParentAcls(parent: Doc, child: Doc) { + return; const dataDoc = parent[DataSym]; for (const key of Object.keys(dataDoc)) { // if the default acl mode is private, then don't inherit the acl-Public permission, but set it to private. const permission = key === 'acl-Public' && Doc.defaultAclPrivate ? AclPrivate : dataDoc[key]; key.startsWith('acl') && distributeAcls(key, permission, child); } - return; } /** @@ -209,24 +215,8 @@ export function SetCachedGroups(groups: string[]) { } function getEffectiveAcl(target: any, user?: string): symbol { const targetAcls = target[AclSym]; - if (targetAcls?.['acl-Me'] === AclAdmin || GetCachedGroupByName(SharingPermissions.Admin)) return AclAdmin; - if (target['acl-' + normalizeEmail(Doc.CurrentUserEmail)]) { - if (target['acl-' + normalizeEmail(Doc.CurrentUserEmail)] == SharingPermissions.Admin) { - return AclAdmin; - } - if (target['acl-' + normalizeEmail(Doc.CurrentUserEmail)] == SharingPermissions.Edit) { - return AclEdit; - } - if (target['acl-' + normalizeEmail(Doc.CurrentUserEmail)] == SharingPermissions.Augment) { - return AclAugment; - } - if (target['acl-' + normalizeEmail(Doc.CurrentUserEmail)] == SharingPermissions.View) { - return AclReadonly; - } - if (target['acl-' + normalizeEmail(Doc.CurrentUserEmail)] == SharingPermissions.None) { - return AclPrivate; - } - } + if (targetAcls?.['acl-Me'] === AclAdmin || GetCachedGroupByName('Admin')) return AclAdmin; + const userChecked = user || Doc.CurrentUserEmail; // if the current user is the author of the document / the current user is a member of the admin group if (targetAcls && Object.keys(targetAcls).length) { let effectiveAcl = AclPrivate; @@ -248,7 +238,7 @@ function getEffectiveAcl(target: any, user?: string): symbol { return DocServer?.Control?.isReadOnly?.() && HierarchyMapping.get(effectiveAcl)!.level < aclLevel.editable ? AclEdit : effectiveAcl; } // authored documents are private until an ACL is set. - const targetAuthor = target.__fields?.author || target.author; // target may be a Doc of Proxy, so check __fields.author and .author + const targetAuthor = target.__fieldTuples?.author || target.author; // target may be a Doc of Proxy, so check __fieldTuples.author and .author if (targetAuthor && targetAuthor !== userChecked) return AclPrivate; return AclAdmin; let acl = AclPrivate; @@ -272,7 +262,7 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc if (!visited) visited = [] as Doc[]; if (!target || visited.includes(target)) return; - if ((target._viewType === CollectionViewType.Docking && visited.length > 1) || Doc.GetProto(visited[0]) !== Doc.GetProto(target)) { + if ((target._type_collection === CollectionViewType.Docking && visited.length > 1) || Doc.GetProto(visited[0]) !== Doc.GetProto(target)) { target[key] = acl; Doc.GetProto(target)[key] = acl; if (target !== Doc.GetProto(target)) { @@ -296,7 +286,7 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc } let dataDocChanged = false; - const dataDoc = target[DataSym]; + const dataDoc = target[DocData]; if (dataDoc && (!inheritingFromCollection || !dataDoc[key] || ReverseHierarchyMap.get(StrCast(dataDoc[key]))! > ReverseHierarchyMap.get(acl)!)) { if (GetEffectiveAcl(dataDoc) === AclAdmin) { dataDoc[key] = acl; @@ -309,13 +299,13 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc // maps over the children of the document DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).forEach(d => { distributeAcls(key, acl, d, inheritingFromCollection, visited); - distributeAcls(key, acl, d[DataSym], inheritingFromCollection, visited); + distributeAcls(key, acl, d[DocData], inheritingFromCollection, visited); }); // maps over the annotations of the document - DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc) + '-annotations']).forEach(d => { + DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc) + '_annotations']).forEach(d => { distributeAcls(key, acl, d, inheritingFromCollection, visited); - distributeAcls(key, acl, d[DataSym], inheritingFromCollection, visited); + distributeAcls(key, acl, d[DocData], inheritingFromCollection, visited); }); } @@ -330,16 +320,16 @@ export function setter(target: any, in_prop: string | symbol | number, value: an // if you're trying to change an acl but don't have Admin access / you're trying to change it to something that isn't an acceptable acl, you can't if (typeof prop === 'string' && prop.startsWith('acl') && (effectiveAcl !== AclAdmin || ![...Object.values(SharingPermissions), undefined].includes(value))) return true; - if (typeof prop === 'string' && prop !== '__id' && prop !== '__fields' && prop.startsWith('_')) { + if (typeof prop === 'string' && prop !== '__id' && prop !== '__fieldTuples' && prop.startsWith('_')) { if (!prop.startsWith('__')) prop = prop.substring(1); if (target.__LAYOUT__) { target.__LAYOUT__[prop] = value; return true; } } - if (target.__fields[prop] instanceof ComputedField) { - if (target.__fields[prop].setterscript && value !== undefined && !(value instanceof ComputedField)) { - return ScriptCast(target.__fields[prop])?.setterscript?.run({ self: target[SelfProxy], this: target[SelfProxy], value }).success ? true : false; + if (target.__fieldTuples[prop] instanceof ComputedField) { + if (target.__fieldTuples[prop].setterscript && value !== undefined && !(value instanceof ComputedField)) { + return ScriptCast(target.__fieldTuples[prop])?.setterscript?.run({ self: target[SelfProxy], this: target[SelfProxy], value }).success ? true : false; } } return _setter(target, prop, value, receiver); @@ -349,14 +339,13 @@ export function getter(target: any, prop: string | symbol, proxy: any): any { // prettier-ignore switch (prop) { case 'then' : return undefined; - case '__fields' : case '__id': - case 'constructor': case 'toString': case 'valueOf': - case 'factory': case 'serializeInfo': + case 'constructor': case 'toString': case 'valueOf': + case 'serializeInfo': case 'factory': return target[prop]; - case AclSym : return target[AclSym]; - case $mobx: return target.__fields[prop]; - case LayoutSym: return target.__LAYOUT__; - case HeightSym: case WidthSym: if (GetEffectiveAcl(target) === AclPrivate) return returnZero; + case DocAcl : return target[DocAcl]; + case $mobx: return target.__fieldTuples[prop]; + case DocLayout: return target.__LAYOUT__; + case Height: case Width: if (GetEffectiveAcl(target) === AclPrivate) return returnZero; default : if (typeof prop === 'symbol') return target[prop]; if (prop.startsWith('isMobX')) return target[prop]; @@ -370,7 +359,7 @@ export function getter(target: any, prop: string | symbol, proxy: any): any { } function getFieldImpl(target: any, prop: string | number, proxy: any, ignoreProto: boolean = false): any { - const field = target.__fields[prop]; + const field = target.__fieldTuples[prop]; const value = field?.[ToValue]?.(proxy); // converts ComputedFields to values, or unpacks ProxyFields into Proxys if (value) return value.value; if (field === undefined && !ignoreProto && prop !== 'proto') { @@ -414,6 +403,7 @@ export function updateFunction(target: any, prop: any, value: any, receiver: any diff?.op === '$addToSet' ? { redo: () => { + console.log('redo $add: ' + prop, diff.items); // bcz: uncomment to log undo receiver[prop].push(...diff.items.map((item: any) => item.value ?? item)); lastValue = ObjectField.MakeCopy(receiver[prop]); }, @@ -430,11 +420,12 @@ export function updateFunction(target: any, prop: any, value: any, receiver: any }); lastValue = ObjectField.MakeCopy(receiver[prop]); }), - prop: '', + prop: 'add ' + diff.items.length + ' items to list', } : diff?.op === '$remFromSet' ? { redo: action(() => { + console.log('redo $rem: ' + prop, diff.items); // bcz: uncomment to log undo diff.items.forEach((item: any) => { const ind = item instanceof SchemaHeaderField ? receiver[prop].findIndex((ele: any) => ele instanceof SchemaHeaderField && ele.heading === item.heading) : receiver[prop].indexOf(item.value ?? item); ind !== -1 && receiver[prop].splice(ind, 1); @@ -454,10 +445,11 @@ export function updateFunction(target: any, prop: any, value: any, receiver: any }); lastValue = ObjectField.MakeCopy(receiver[prop]); }, - prop: '', + prop: 'remove ' + diff.items.length + ' items from list', } : { redo: () => { + console.log('redo list: ' + prop, receiver[prop]); // bcz: uncomment to log undo receiver[prop] = ObjectField.MakeCopy(newValue as List<any>); lastValue = ObjectField.MakeCopy(receiver[prop]); }, @@ -466,7 +458,7 @@ export function updateFunction(target: any, prop: any, value: any, receiver: any receiver[prop] = ObjectField.MakeCopy(prevValue as List<any>); lastValue = ObjectField.MakeCopy(receiver[prop]); }, - prop: '', + prop: 'assign list', } ); } |