diff options
author | bobzel <zzzman@gmail.com> | 2021-03-08 10:00:36 -0500 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2021-03-08 10:00:36 -0500 |
commit | 94f2e575b95c6edd5410d440f7410d712c90b5db (patch) | |
tree | bfdd27227a9ea9b07ee62adf3ad73db26e71942b | |
parent | ca6e8145c5883e32f4cc65edbfff245cdde326ed (diff) |
added doc data content synching to Git-like operations.
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 2 | ||||
-rw-r--r-- | src/client/util/GroupManager.tsx | 8 | ||||
-rw-r--r-- | src/client/views/collections/CollectionView.tsx | 27 |
3 files changed, 28 insertions, 9 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 8b425f929..ccdfeed5f 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -988,7 +988,7 @@ export class CurrentUserUtils { static async updateUserDocument(doc: Doc, sharingDocumentId: string, linkDatabaseId: string) { if (!doc.globalGroupDatabase) doc.globalGroupDatabase = Docs.Prototypes.MainGroupDocument(); const groups = await DocListCastAsync((doc.globalGroupDatabase as Doc).data); - reaction(() => DateCast((doc.globalGroupDatabase as Doc).lastModified), + reaction(() => DateCast((doc.globalGroupDatabase as Doc)["data-lastModified"]), async () => { const groups = await DocListCastAsync((doc.globalGroupDatabase as Doc).data); const mygroups = groups?.filter(group => JSON.parse(StrCast(group.members)).includes(Doc.CurrentUserEmail)) || []; diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index 6458de0ed..68af67a3b 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -146,7 +146,7 @@ export class GroupManager extends React.Component<{}> { addGroup(groupDoc: Doc): boolean { if (this.GroupManagerDoc) { Doc.AddDocToList(this.GroupManagerDoc, "data", groupDoc); - this.GroupManagerDoc.lastModified = new DateField; + this.GroupManagerDoc["data-lastModified"] = new DateField; return true; } return false; @@ -167,7 +167,7 @@ export class GroupManager extends React.Component<{}> { const index = DocListCast(this.GroupManagerDoc.data).findIndex(grp => grp === group); index !== -1 && Cast(this.GroupManagerDoc.data, listSpec(Doc), [])?.splice(index, 1); } - this.GroupManagerDoc.lastModified = new DateField; + this.GroupManagerDoc["data-lastModified"] = new DateField; if (group === this.currentGroup) { this.currentGroup = undefined; } @@ -188,7 +188,7 @@ export class GroupManager extends React.Component<{}> { !memberList.includes(email) && memberList.push(email); groupDoc.members = JSON.stringify(memberList); SharingManager.Instance.shareWithAddedMember(groupDoc, email); - this.GroupManagerDoc && (this.GroupManagerDoc.lastModified = new DateField); + this.GroupManagerDoc && (this.GroupManagerDoc["data-lastModified"] = new DateField); } } @@ -205,7 +205,7 @@ export class GroupManager extends React.Component<{}> { const user = memberList.splice(index, 1)[0]; groupDoc.members = JSON.stringify(memberList); SharingManager.Instance.removeMember(groupDoc, email); - this.GroupManagerDoc && (this.GroupManagerDoc.lastModified = new DateField); + this.GroupManagerDoc && (this.GroupManagerDoc["data-lastModified"] = new DateField); } } } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index c1db8fd0b..5d1e8b41c 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -3,12 +3,12 @@ import { observer } from "mobx-react"; import * as React from 'react'; import 'react-image-lightbox-with-rotate/style.css'; // This only needs to be imported once in your app import { DateField } from '../../../fields/DateField'; -import { AclAddonly, AclAdmin, AclEdit, AclPrivate, AclReadonly, AclSym, DataSym, Doc, DocListCast, DocListCastAsync } from '../../../fields/Doc'; +import { AclAddonly, AclAdmin, AclEdit, AclPrivate, AclReadonly, AclSym, DataSym, Doc, DocListCast, DocListCastAsync, Field } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; import { ScriptField } from '../../../fields/ScriptField'; -import { Cast, ScriptCast, StrCast } from '../../../fields/Types'; +import { Cast, ScriptCast, StrCast, DateCast } from '../../../fields/Types'; import { denormalizeEmail, distributeAcls, GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util'; import { returnFalse } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; @@ -277,6 +277,21 @@ export class CollectionView extends Touchable<CollectionViewProps> { } } + // synchs matching documents on the two branches that are being merged/pulled + // currently this just synchs the main 'fieldKey' component of the data since + // we don't have individual timestamps for all fields -- this is a problematic design issue. + static synchDocs(bd: Doc, md: Doc) { + const fieldKey = Doc.LayoutFieldKey(md); + let bdate = DateCast(bd[`${fieldKey}-lastModified`])?.date; + let mdate = DateCast(md[`${fieldKey}-lastModified`])?.date; + if (bdate === mdate || bdate > mdate) return; + const bdproto = bd && Doc.GetProto(bd); + if (bdproto && md) { + bdproto[fieldKey] = ObjectField.MakeCopy(md[fieldKey] as ObjectField); + bdproto[`${fieldKey}-lastModified`] = ObjectField.MakeCopy(md[`${fieldKey}-lastModified`] as ObjectField); + } + } + // pulls documents onto a branch from the branch's master // if a document exists on master but not on the branch, it is branched and added // NOTE: need to set a timestamp on the branch that is equal to the master's last merge timestamp. @@ -290,6 +305,11 @@ export class CollectionView extends Touchable<CollectionViewProps> { const branchMasterMainDocProtos = branchMasterMainDocs?.map(doc => Doc.GetProto(doc)); // get documents on master that don't have a corresponding master doc (form a branch doc), and ... const newDocsFromMaster = masterMainDocs?.filter(md => !branchMasterMainDocProtos?.includes(Doc.GetProto(md))); + const oldDocsFromMaster = masterMainDocs?.filter(md => branchMasterMainDocProtos?.includes(Doc.GetProto(md))); + oldDocsFromMaster?.forEach(md => { + const bd = branchMainDocs?.find(bd => (Cast(bd.branchOf, Doc, null) || bd) === md); + bd && CollectionView.synchDocs(bd, md); + }) // make branch clones of them, then add them to the branch const newlyBranchedDocs = await Promise.all(newDocsFromMaster?.map(async md => (await Doc.MakeClone(md, false, true)).clone) || []); newlyBranchedDocs.forEach(nd => { @@ -304,8 +324,6 @@ export class CollectionView extends Touchable<CollectionViewProps> { // merges all branches from the master branch by first merging the top-level collection of documents, // and then merging all the annotations on those documents. - // NOTE: "merging" only means making sure that documents in the branches are on master -- it does not - // currently update the state of those documents to be identical. // TODO: need to add an incrementing timestamp whenever anything merges. don't allow a branch to merge if it's last pull timestamp isn't equal to the last merge timestamp. static mergeWithMaster = async (master: Doc, suffix = "") => { const branches = await DocListCastAsync(master.branches); @@ -327,6 +345,7 @@ export class CollectionView extends Touchable<CollectionViewProps> { } Doc.AddDocToList(master, Doc.LayoutFieldKey(master) + suffix, masterChild); // add the masterChild to master (if it's already there, this is a no-op) masterChild.context = master; + CollectionView.synchDocs(Doc.GetProto(masterChild), bd); }); const masterChildren = await DocListCastAsync(master[Doc.LayoutFieldKey(master) + suffix]); masterChildren?.forEach(async mc => { // see if any master children |