diff options
Diffstat (limited to 'src/client/documents')
| -rw-r--r-- | src/client/documents/Documents.ts | 132 | ||||
| -rw-r--r-- | src/client/documents/Gitlike.ts | 226 |
2 files changed, 158 insertions, 200 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 98469a2f9..3e89c8347 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -2,7 +2,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { action, runInAction } from 'mobx'; import { basename } from 'path'; import { DateField } from '../../fields/DateField'; -import { Doc, DocListCast, DocListCastAsync, Field, Initializing, Opt, updateCachedAcls } from '../../fields/Doc'; +import { Doc, DocListCast, Field, Initializing, Opt, updateCachedAcls } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; import { HtmlField } from '../../fields/HtmlField'; import { InkField, PointData } from '../../fields/InkField'; @@ -39,7 +39,6 @@ import { DataVizBox } from '../views/nodes/DataVizBox/DataVizBox'; import { DocFocusOptions, OpenWhere, OpenWhereMod } from '../views/nodes/DocumentView'; import { EquationBox } from '../views/nodes/EquationBox'; import { FieldViewProps } from '../views/nodes/FieldView'; -import { FilterBox } from '../views/nodes/FilterBox'; import { FormattedTextBox } from '../views/nodes/formattedText/FormattedTextBox'; import { FunctionPlotBox } from '../views/nodes/FunctionPlotBox'; import { ImageBox } from '../views/nodes/ImageBox'; @@ -201,6 +200,8 @@ export class DocumentOptions { 'icon-nativeWidth'?: NUMt = new NumInfo('native width of icon view'); 'icon-nativeHeight'?: NUMt = new NumInfo('native height of icon view'); 'dragFactory-count'?: NUMt = new NumInfo('number of items created from a drag button (used for setting title with incrementing index)'); + openFactoryLocation?: string; // an OpenWhere value to place the factory created document + openFactoryAsDelegate?: boolean; // lat?: number; lng?: number; infoWindowOpen?: boolean; @@ -221,6 +222,8 @@ export class DocumentOptions { autoPlayAnchors?: boolean; // whether to play audio/video when an anchor is clicked in a stackedTimeline. dontPlayLinkOnSelect?: boolean; // whether an audio/video should start playing when a link is followed to it. toolTip?: string; // tooltip to display on hover + toolType?: string; // type of pen tool + expertMode?: boolean; // something available only in expert (not novice) mode contextMenuFilters?: List<ScriptField>; contextMenuScripts?: List<ScriptField>; contextMenuLabels?: List<string>; @@ -242,6 +245,7 @@ export class DocumentOptions { childContextMenuIcons?: List<string>; followLinkZoom?: boolean; // whether to zoom to the target of a link hideLinkButton?: boolean; // whether the blue link counter button should be hidden + disableDocBrushing?: boolean; // whether to suppress border highlighting hideDecorationTitle?: boolean; hideOpenButton?: boolean; hideResizeHandles?: boolean; @@ -262,6 +266,9 @@ export class DocumentOptions { activeFrame?: number; // the active frame of a document in a frame base collection appearFrame?: number; // the frame in which the document appears viewTransitionTime?: number; // transition duration for view parameters + presPanX?: number; // panX saved as a view spec + presPanY?: number; // panY saved as a view spec + presViewScale?: number; // viewScale saved as a view Spec presTransition?: number; //the time taken for the transition TO a document presDuration?: number; //the duration of the slide in presentation view presZoomText?: boolean; // whether text anchors should shown in a larger box when following links to make them stand out @@ -336,6 +343,7 @@ export class DocumentOptions { strokeWidth?: number; freezeChildren?: string; // whether children are now allowed to be added and or removed from a collection treeViewHideTitle?: boolean; // whether to hide the top document title of a tree view + treeViewHideUnrendered?: boolean; // tells tree view not to display documents that have an 'unrendered' tag unless they also have a treeViewFieldKey tag (presBox) treeViewHideHeaderIfTemplate?: boolean; // whether to hide the header for a document in a tree view only if a childLayoutTemplate is provided (presBox) treeViewHideHeader?: boolean; // whether to hide the header for a document in a tree view treeViewHideHeaderFields?: boolean; // whether to hide the drop down options for tree view items. @@ -400,7 +408,6 @@ export namespace Docs { nativeDimModifiable: true, nativeHeightUnfrozen: true, forceReflow: true, - links: '@links(self)', }, }, ], @@ -408,42 +415,35 @@ export namespace Docs { DocumentType.SEARCH, { layout: { view: SearchBox, dataField: defaultDataKey }, - options: { _width: 400, links: '@links(self)' }, - }, - ], - [ - DocumentType.FILTER, - { - layout: { view: FilterBox, dataField: defaultDataKey }, - options: { _width: 400, links: '@links(self)' }, + options: { _width: 400 }, }, ], [ DocumentType.COLOR, { layout: { view: ColorBox, dataField: defaultDataKey }, - options: { _nativeWidth: 220, _nativeHeight: 300, links: '@links(self)' }, + options: { _nativeWidth: 220, _nativeHeight: 300 }, }, ], [ DocumentType.IMG, { layout: { view: ImageBox, dataField: defaultDataKey }, - options: { links: '@links(self)' }, + options: {}, }, ], [ DocumentType.WEB, { layout: { view: WebBox, dataField: defaultDataKey }, - options: { _height: 300, _fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, links: '@links(self)' }, + options: { _height: 300, _fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true }, }, ], [ DocumentType.COL, { layout: { view: CollectionView, dataField: defaultDataKey }, - options: { _fitWidth: true, _panX: 0, _panY: 0, _viewScale: 1, links: '@links(self)' }, + options: { _fitWidth: true, _panX: 0, _panY: 0, _viewScale: 1 }, }, ], [ @@ -457,35 +457,35 @@ export namespace Docs { DocumentType.VID, { layout: { view: VideoBox, dataField: defaultDataKey }, - options: { _currentTimecode: 0, links: '@links(self)' }, + options: { _currentTimecode: 0 }, }, ], [ DocumentType.AUDIO, { layout: { view: AudioBox, dataField: defaultDataKey }, - options: { _height: 100, backgroundColor: 'lightGray', _fitWidth: true, forceReflow: true, nativeDimModifiable: true, links: '@links(self)' }, + options: { _height: 100, forceReflow: true, nativeDimModifiable: true }, }, ], [ DocumentType.REC, { layout: { view: VideoBox, dataField: defaultDataKey }, - options: { _height: 100, backgroundColor: 'pink', links: '@links(self)' }, + options: { _height: 100, backgroundColor: 'pink' }, }, ], [ DocumentType.PDF, { layout: { view: PDFBox, dataField: defaultDataKey }, - options: { _curPage: 1, _fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true, links: '@links(self)' }, + options: { _curPage: 1, _fitWidth: true, nativeDimModifiable: true, nativeHeightUnfrozen: true }, }, ], [ DocumentType.MAP, { layout: { view: MapBox, dataField: defaultDataKey }, - options: { _height: 600, _width: 800, nativeDimModifiable: true, links: '@links(self)' }, + options: { _height: 600, _width: 800, nativeDimModifiable: true }, }, ], [ @@ -506,7 +506,6 @@ export namespace Docs { description: '', showCaption: 'description', backgroundColor: 'lightblue', // lightblue is default color for linking dot and link documents text comment area - links: '@links(self)', _removeDropProperties: new List(['isLinkButton']), }, }, @@ -531,7 +530,7 @@ export namespace Docs { DocumentType.SCRIPTING, { layout: { view: ScriptingBox, dataField: defaultDataKey }, - options: { links: '@links(self)' }, + options: {}, }, ], [ @@ -544,56 +543,56 @@ export namespace Docs { DocumentType.LABEL, { layout: { view: LabelBox, dataField: defaultDataKey }, - options: { links: '@links(self)', _singleLine: true }, + options: { _singleLine: true }, }, ], [ DocumentType.EQUATION, { layout: { view: EquationBox, dataField: defaultDataKey }, - options: { links: '@links(self)', nativeDimModifiable: true, fontSize: '14px', hideResizeHandles: true, hideDecorationTitle: true }, + options: { nativeDimModifiable: true, fontSize: '14px', hideResizeHandles: true, hideDecorationTitle: true }, }, ], [ DocumentType.FUNCPLOT, { layout: { view: FunctionPlotBox, dataField: defaultDataKey }, - options: { nativeDimModifiable: true, links: '@links(self)' }, + options: { nativeDimModifiable: true }, }, ], [ DocumentType.BUTTON, { layout: { view: LabelBox, dataField: 'onClick' }, - options: { links: '@links(self)' }, + options: {}, }, ], [ DocumentType.SLIDER, { layout: { view: SliderBox, dataField: defaultDataKey }, - options: { links: '@links(self)' }, + options: {}, }, ], [ DocumentType.PRES, { layout: { view: PresBox, dataField: defaultDataKey }, - options: { links: '@links(self)' }, + options: {}, }, ], [ DocumentType.FONTICON, { - layout: { view: FontIconBox, dataField: defaultDataKey }, - options: { allowClickBeforeDoubleClick: true, hideLinkButton: true, _width: 40, _height: 40, borderRounding: '100%', links: '@links(self)' }, + layout: { view: FontIconBox, dataField: 'icon' }, + options: { allowClickBeforeDoubleClick: true, hideLinkButton: true, _width: 40, _height: 40 }, }, ], [ DocumentType.WEBCAM, { layout: { view: RecordingBox, dataField: defaultDataKey }, - options: { links: '@links(self)' }, + options: {}, }, ], [ @@ -607,7 +606,7 @@ export namespace Docs { DocumentType.MARKER, { layout: { view: CollectionView, dataField: defaultDataKey }, - options: { links: '@links(self)', hideLinkButton: true, pointerEvents: 'none' }, + options: { hideLinkButton: true, pointerEvents: 'none' }, }, ], [ @@ -615,21 +614,21 @@ export namespace Docs { { // NOTE: this is unused!! ink fields are filled in directly within the InkDocument() method layout: { view: InkingStroke, dataField: defaultDataKey }, - options: { links: '@links(self)' }, + options: {}, }, ], [ DocumentType.SCREENSHOT, { layout: { view: ScreenshotBox, dataField: defaultDataKey }, - options: { links: '@links(self)' }, + options: {}, }, ], [ DocumentType.COMPARISON, { layout: { view: ComparisonBox, dataField: defaultDataKey }, - options: { clipWidth: 50, nativeDimModifiable: true, backgroundColor: 'gray', targetDropAction: 'alias', links: '@links(self)' }, + options: { clipWidth: 50, nativeDimModifiable: true, backgroundColor: 'gray', targetDropAction: 'alias' }, }, ], [ @@ -644,21 +643,21 @@ export namespace Docs { DocumentType.GROUP, { layout: { view: EmptyBox, dataField: defaultDataKey }, - options: { links: '@links(self)' }, + options: {}, }, ], [ DocumentType.DATAVIZ, { layout: { view: DataVizBox, dataField: defaultDataKey }, - options: { _fitWidth: true, nativeDimModifiable: true, links: '@links(self)' }, + options: { _fitWidth: true, nativeDimModifiable: true }, }, ], [ DocumentType.LOADING, { layout: { view: LoadingBox, dataField: '' }, - options: { _fitWidth: true, _fitHeight: true, nativeDimModifiable: true, links: '@links(self)' }, + options: { _fitWidth: true, _fitHeight: true, nativeDimModifiable: true }, }, ], ]); @@ -885,15 +884,7 @@ export namespace Docs { } export function AudioDocument(url: string, options: DocumentOptions = {}, overwriteDoc?: Doc) { - return InstanceFromProto( - Prototypes.get(DocumentType.AUDIO), - new AudioField(url), - { ...options, backgroundColor: ComputedField.MakeFunction("this._mediaState === 'playing' ? 'green':'gray'") as any }, - undefined, - undefined, - undefined, - overwriteDoc - ); + return InstanceFromProto(Prototypes.get(DocumentType.AUDIO), new AudioField(url), options, undefined, undefined, undefined, overwriteDoc); } export function RecordingDocument(url: string, options: DocumentOptions = {}) { @@ -996,7 +987,6 @@ export namespace Docs { I.creationDate = new DateField(); I['acl-Public'] = Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment; //I['acl-Override'] = SharingPermissions.Unset; - I.links = ComputedField.MakeFunction('links(self)'); I[Initializing] = false; return I; } @@ -1260,7 +1250,7 @@ export namespace DocUtils { return Field.toString(d[facetKey] as Field).includes(value); }); // if we're ORing them together, the default return is false, and we return true for a doc if it satisfies any one set of criteria - if ((parentCollection?.currentFilter as Doc)?.filterBoolean === 'OR') { + if (parentCollection?.filterBoolean === 'OR') { if (satisfiesUnsetsFacets && satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true; } // if we're ANDing them together, the default return is true, and we return false for a doc if it doesn't satisfy any set of criteria @@ -1286,38 +1276,6 @@ export namespace DocUtils { return rangeFilteredDocs; } - export function Publish(promoteDoc: Doc, targetID: string, addDoc: any, remDoc: any) { - targetID = targetID.replace(/^-/, '').replace(/\([0-9]*\)$/, ''); - DocServer.GetRefField(targetID).then(doc => { - if (promoteDoc !== doc) { - let copy = doc as Doc; - if (copy) { - Doc.Overwrite(promoteDoc, copy, true); - } else { - copy = Doc.MakeCopy(promoteDoc, true, targetID); - } - !doc && (copy.title = undefined) && (Doc.GetProto(copy).title = targetID); - addDoc && addDoc(copy); - remDoc && remDoc(promoteDoc); - if (!doc) { - DocListCastAsync(promoteDoc.links).then(links => { - links && - links.map(async link => { - if (link) { - const a1 = await Cast(link.anchor1, Doc); - if (a1 && Doc.AreProtosEqual(a1, promoteDoc)) link.anchor1 = copy; - const a2 = await Cast(link.anchor2, Doc); - if (a2 && Doc.AreProtosEqual(a2, promoteDoc)) link.anchor2 = copy; - LinkManager.Instance.deleteLink(link); - LinkManager.Instance.addLink(link); - } - }); - }); - } - } - }); - } - export function DefaultFocus(doc: Doc, options: DocFocusOptions) { return undefined; } @@ -1400,6 +1358,8 @@ export namespace DocUtils { const script = scripts[key]; if (ScriptCast(doc[key])?.script.originalScript !== scripts[key] && script) { doc[key] = ScriptField.MakeScript(script, { + self: Doc.name, + this: Doc.name, dragData: DragManager.DocumentDragData.name, value: 'any', _readOnly_: 'boolean', @@ -1715,7 +1675,7 @@ export namespace DocUtils { export function LeavePushpin(doc: Doc, annotationField: string) { if (doc.followLinkToggle) return undefined; const context = Cast(doc.context, Doc, null) ?? Cast(doc.annotationOn, Doc, null); - const hasContextAnchor = DocListCast(doc.links).some(l => (l.anchor2 === doc && Cast(l.anchor1, Doc, null)?.annotationOn === context) || (l.anchor1 === doc && Cast(l.anchor2, Doc, null)?.annotationOn === context)); + const hasContextAnchor = LinkManager.Links(doc).some(l => (l.anchor2 === doc && Cast(l.anchor1, Doc, null)?.annotationOn === context) || (l.anchor1 === doc && Cast(l.anchor2, Doc, null)?.annotationOn === context)); if (context && !hasContextAnchor && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) { const pushpin = Docs.Create.FontIconDocument({ title: 'pushpin', @@ -1726,6 +1686,7 @@ export namespace DocUtils { x: Cast(doc.x, 'number', null), y: Cast(doc.y, 'number', null), backgroundColor: '#ACCEF7', + hideAllLinks: true, _width: 15, _height: 15, _xPadding: 0, @@ -1909,11 +1870,8 @@ export namespace DocUtils { } ScriptingGlobals.add('Docs', Docs); -ScriptingGlobals.add(function copyDragFactory(dragFactory: Doc) { - return DocUtils.copyDragFactory(dragFactory); -}); -ScriptingGlobals.add(function delegateDragFactory(dragFactory: Doc) { - return DocUtils.delegateDragFactory(dragFactory); +ScriptingGlobals.add(function copyDragFactory(dragFactory: Doc, asDelegate?: boolean) { + return dragFactory instanceof Doc ? (asDelegate ? DocUtils.delegateDragFactory(dragFactory) : DocUtils.copyDragFactory(dragFactory)) : dragFactory; }); ScriptingGlobals.add(function makeDelegate(proto: any) { const d = Docs.Create.DelegateDocument(proto, { title: 'child of ' + proto.title }); diff --git a/src/client/documents/Gitlike.ts b/src/client/documents/Gitlike.ts index 575c984f5..5e2baf924 100644 --- a/src/client/documents/Gitlike.ts +++ b/src/client/documents/Gitlike.ts @@ -1,118 +1,118 @@ -import { Doc, DocListCast, DocListCastAsync, Field } from "../../fields/Doc"; -import { List } from "../../fields/List"; -import { Cast, DateCast } from "../../fields/Types"; -import { DateField } from "../../fields/DateField"; -import { Id } from "../../fields/FieldSymbols"; +// import { Doc, DocListCast, DocListCastAsync, Field } from "../../fields/Doc"; +// import { List } from "../../fields/List"; +// import { Cast, DateCast } from "../../fields/Types"; +// import { DateField } from "../../fields/DateField"; +// import { Id } from "../../fields/FieldSymbols"; -// 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. -function GitlikeSynchDocs(bd: Doc, md: Doc) { - const fieldKey = Doc.LayoutFieldKey(md); - const bdate = DateCast(bd[`${fieldKey}-lastModified`])?.date; - const mdate = DateCast(md[`${fieldKey}-lastModified`])?.date; - const bdproto = bd && Doc.GetProto(bd); - if (bdate !== mdate && bdate <= mdate) { - if (bdproto && md) { - bdproto[fieldKey] = Field.Copy(md[fieldKey]); - bdproto[`${fieldKey}-lastModified`] = new DateField(); - } - } - const bldate = DateCast(bd._lastModified)?.date; - const mldate = DateCast(md._lastModified)?.date; - if (bldate === mldate || bldate > mldate) return; - if (bdproto && md) { - bd.x = Field.Copy(md.x); - bd.y = Field.Copy(md.y); - bd.width = Field.Copy(md.width); - bd.height = Field.Copy(md.height); - bdproto._lastModified = new DateField(); - } -} +// // 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. +// function GitlikeSynchDocs(bd: Doc, md: Doc) { +// const fieldKey = Doc.LayoutFieldKey(md); +// const bdate = DateCast(bd[`${fieldKey}-lastModified`])?.date; +// const mdate = DateCast(md[`${fieldKey}-lastModified`])?.date; +// const bdproto = bd && Doc.GetProto(bd); +// if (bdate !== mdate && bdate <= mdate) { +// if (bdproto && md) { +// bdproto[fieldKey] = Field.Copy(md[fieldKey]); +// bdproto[`${fieldKey}-lastModified`] = new DateField(); +// } +// } +// const bldate = DateCast(bd._lastModified)?.date; +// const mldate = DateCast(md._lastModified)?.date; +// if (bldate === mldate || bldate > mldate) return; +// if (bdproto && md) { +// bd.x = Field.Copy(md.x); +// bd.y = Field.Copy(md.y); +// bd.width = Field.Copy(md.width); +// bd.height = Field.Copy(md.height); +// bdproto._lastModified = new DateField(); +// } +// } -// 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. -async function GitlikePullFromMaster(branch: Doc, suffix = "") { - const masterMain = Cast(branch.branchOf, Doc, null); - // get the set of documents on both the branch and master - const masterMainDocs = masterMain && await DocListCastAsync(masterMain[Doc.LayoutFieldKey(masterMain) + suffix]); - const branchMainDocs = await DocListCastAsync(branch[Doc.LayoutFieldKey(branch) + suffix]); - // get the master documents that correspond to the branch documents - const branchMasterMainDocs = branchMainDocs?.map(bd => Cast(bd.branchOf, Doc, null) || bd); - 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 && GitlikeSynchDocs(bd, md); - }); - const cloneMap = new Map<string, Doc>(); cloneMap.set(masterMain[Id], branch); - // 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, cloneMap)).clone) || []); - newlyBranchedDocs.forEach(nd => { - Doc.AddDocToList(branch, Doc.LayoutFieldKey(branch) + suffix, nd); - nd.context = branch; - }); - // if a branch doc's corresponding main branch doc doesn't have a context, then it was deleted. - const remDocsFromMaster = branchMainDocs?.filter(bd => Cast(bd.branchOf, Doc, null) && !Cast(bd.branchOf, Doc, null)?.context); - // so then remove all the deleted main docs from this branch. - remDocsFromMaster?.forEach(rd => Doc.RemoveDocFromList(branch, Doc.LayoutFieldKey(branch) + suffix, rd)); -} +// // 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. +// async function GitlikePullFromMaster(branch: Doc, suffix = "") { +// const masterMain = Cast(branch.branchOf, Doc, null); +// // get the set of documents on both the branch and master +// const masterMainDocs = masterMain && await DocListCastAsync(masterMain[Doc.LayoutFieldKey(masterMain) + suffix]); +// const branchMainDocs = await DocListCastAsync(branch[Doc.LayoutFieldKey(branch) + suffix]); +// // get the master documents that correspond to the branch documents +// const branchMasterMainDocs = branchMainDocs?.map(bd => Cast(bd.branchOf, Doc, null) || bd); +// 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 && GitlikeSynchDocs(bd, md); +// }); +// const cloneMap = new Map<string, Doc>(); cloneMap.set(masterMain[Id], branch); +// // 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, cloneMap)).clone) || []); +// newlyBranchedDocs.forEach(nd => { +// Doc.AddDocToList(branch, Doc.LayoutFieldKey(branch) + suffix, nd); +// nd.context = branch; +// }); +// // if a branch doc's corresponding main branch doc doesn't have a context, then it was deleted. +// const remDocsFromMaster = branchMainDocs?.filter(bd => Cast(bd.branchOf, Doc, null) && !Cast(bd.branchOf, Doc, null)?.context); +// // so then remove all the deleted main docs from this branch. +// remDocsFromMaster?.forEach(rd => Doc.RemoveDocFromList(branch, Doc.LayoutFieldKey(branch) + suffix, rd)); +// } -// 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. -// 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. -async function GitlikeMergeWithMaster(master: Doc, suffix = "") { - const branches = await DocListCastAsync(master.branches); - branches?.map(async branch => { - const branchChildren = await DocListCastAsync(branch[Doc.LayoutFieldKey(branch) + suffix]); - branchChildren && await Promise.all(branchChildren.map(async bd => { - const cloneMap = new Map<string, Doc>(); cloneMap.set(master[Id], branch); - // see if the branch's child exists on master. - const masterChild = Cast(bd.branchOf, Doc, null) || (await Doc.MakeClone(bd, false, true, cloneMap)).clone; - // if the branch's child didn't exist on master, we make a branch clone of the child to add to master. - // however, since master is supposed to have the "main" clone, and branches, the "branch" clones, we have to reverse the fields - // on the branch child and master clone. - if (masterChild.branchOf) { - const branchDocProto = Doc.GetProto(bd); - const masterChildProto = Doc.GetProto(masterChild); - const branchTitle = bd.title; - branchDocProto.title = masterChildProto.title; - masterChildProto.title = branchTitle; - masterChildProto.branchOf = masterChild.branchOf = undefined; // the master child should not be a branch of the branch child, so unset 'branchOf' - masterChildProto.branches = new List<Doc>([bd]); // the master child's branches needs to include the branch child - Doc.RemoveDocFromList(branchDocProto, "branches", masterChildProto); // the branch child should not have the master child in its branch list. - branchDocProto.branchOf = masterChild; // the branch child is now a branch of the master child - } - 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; - GitlikeSynchDocs(masterChild, bd);//Doc.GetProto(masterChild), bd); - })); - const masterChildren = await DocListCastAsync(master[Doc.LayoutFieldKey(master) + suffix]); - masterChildren?.forEach(mc => { // see if any master children - if (!branchChildren?.find(bc => bc.branchOf === mc)) { // are not in the list of children for this branch. - Doc.RemoveDocFromList(master, Doc.LayoutFieldKey(master) + suffix, mc); // if so, delete the master child since the branch has deleted it. - mc.context = undefined; // NOTE if we merge a branch that didn't do a pull, it will look like the branch deleted documents -- need edit timestamps that prevent merging if branch isn't up-to-date with last edit timestamp - } - }); - }); -} +// // 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. +// // 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. +// async function GitlikeMergeWithMaster(master: Doc, suffix = "") { +// const branches = await DocListCastAsync(master.branches); +// branches?.map(async branch => { +// const branchChildren = await DocListCastAsync(branch[Doc.LayoutFieldKey(branch) + suffix]); +// branchChildren && await Promise.all(branchChildren.map(async bd => { +// const cloneMap = new Map<string, Doc>(); cloneMap.set(master[Id], branch); +// // see if the branch's child exists on master. +// const masterChild = Cast(bd.branchOf, Doc, null) || (await Doc.MakeClone(bd, false, true, cloneMap)).clone; +// // if the branch's child didn't exist on master, we make a branch clone of the child to add to master. +// // however, since master is supposed to have the "main" clone, and branches, the "branch" clones, we have to reverse the fields +// // on the branch child and master clone. +// if (masterChild.branchOf) { +// const branchDocProto = Doc.GetProto(bd); +// const masterChildProto = Doc.GetProto(masterChild); +// const branchTitle = bd.title; +// branchDocProto.title = masterChildProto.title; +// masterChildProto.title = branchTitle; +// masterChildProto.branchOf = masterChild.branchOf = undefined; // the master child should not be a branch of the branch child, so unset 'branchOf' +// masterChildProto.branches = new List<Doc>([bd]); // the master child's branches needs to include the branch child +// Doc.RemoveDocFromList(branchDocProto, "branches", masterChildProto); // the branch child should not have the master child in its branch list. +// branchDocProto.branchOf = masterChild; // the branch child is now a branch of the master child +// } +// 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; +// GitlikeSynchDocs(masterChild, bd);//Doc.GetProto(masterChild), bd); +// })); +// const masterChildren = await DocListCastAsync(master[Doc.LayoutFieldKey(master) + suffix]); +// masterChildren?.forEach(mc => { // see if any master children +// if (!branchChildren?.find(bc => bc.branchOf === mc)) { // are not in the list of children for this branch. +// Doc.RemoveDocFromList(master, Doc.LayoutFieldKey(master) + suffix, mc); // if so, delete the master child since the branch has deleted it. +// mc.context = undefined; // NOTE if we merge a branch that didn't do a pull, it will look like the branch deleted documents -- need edit timestamps that prevent merging if branch isn't up-to-date with last edit timestamp +// } +// }); +// }); +// } -// performs a "git"-like task: pull or merge -// if pull, then target is a specific branch document that will be updated from its associated master -// if merge, then target is the master doc that will merge in all branches associated with it. -// TODO: parameterize 'merge' to specify which branch(es) should be merged. -// extend 'merge' to allow a specific branch to be merge target (not just master); -// make pull/merge be recursive (ie, this func currently just operates on the main doc and its children) -export async function BranchTask(target: Doc, action: "pull" | "merge") { - const func = action === "pull" ? GitlikePullFromMaster : GitlikeMergeWithMaster; - await func(target, ""); - await DocListCast(target[Doc.LayoutFieldKey(target)]).forEach(async targetChild => func(targetChild, "-annotations")); - await DocListCast(target[Doc.LayoutFieldKey(target)]).forEach(async targetChild => func(targetChild, "-sidebar")); -} +// // performs a "git"-like task: pull or merge +// // if pull, then target is a specific branch document that will be updated from its associated master +// // if merge, then target is the master doc that will merge in all branches associated with it. +// // TODO: parameterize 'merge' to specify which branch(es) should be merged. +// // extend 'merge' to allow a specific branch to be merge target (not just master); +// // make pull/merge be recursive (ie, this func currently just operates on the main doc and its children) +// export async function BranchTask(target: Doc, action: "pull" | "merge") { +// const func = action === "pull" ? GitlikePullFromMaster : GitlikeMergeWithMaster; +// await func(target, ""); +// await DocListCast(target[Doc.LayoutFieldKey(target)]).forEach(async targetChild => func(targetChild, "-annotations")); +// await DocListCast(target[Doc.LayoutFieldKey(target)]).forEach(async targetChild => func(targetChild, "-sidebar")); +// } -export async function BranchCreate(target: Doc) { - return (await Doc.MakeClone(target, false, true)).clone; -}
\ No newline at end of file +// export async function BranchCreate(target: Doc) { +// return (await Doc.MakeClone(target, false, true)).clone; +// } |
