diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/documents/Documents.ts | 2 | ||||
-rw-r--r-- | src/client/util/DropConverter.ts | 4 | ||||
-rw-r--r-- | src/client/views/DocComponent.tsx | 4 | ||||
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 2 | ||||
-rw-r--r-- | src/client/views/InkingControl.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/CollectionStackingView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/CollectionSubView.tsx | 8 | ||||
-rw-r--r-- | src/client/views/collections/CollectionTreeView.tsx | 6 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/ButtonBox.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 8 | ||||
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 2 | ||||
-rw-r--r-- | src/new_fields/Doc.ts | 63 | ||||
-rw-r--r-- | src/new_fields/documentSchemas.ts | 2 |
14 files changed, 55 insertions, 54 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e86ed52f3..6132f787b 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -76,7 +76,7 @@ export interface DocumentOptions { preventTreeViewOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expande/collapse state to be independent of other views of the same document in the tree view layout?: string | Doc; hideHeadings?: boolean; // whether stacking view column headings should be hidden - isTemplateField?: boolean; + isTemplateForField?: string; // the field key for which the containing document is a rendering template isTemplateDoc?: boolean; templates?: List<string>; viewType?: number; diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index 3e2cc6a2e..66caf52cb 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -8,7 +8,7 @@ import { Docs } from "../documents/Documents"; import { ScriptField } from "../../new_fields/ScriptField"; export function makeTemplate(doc: Doc): boolean { - const layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateField ? doc.layout : doc; + const layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc; const layout = StrCast(layoutDoc.layout).match(/fieldKey={'[^']*'}/)![0]; const fieldKey = layout.replace("fieldKey={'", "").replace(/'}$/, ""); const docs = DocListCast(layoutDoc[fieldKey]); @@ -28,7 +28,7 @@ export function convertDropDataToButtons(data: DragManager.DocumentDragData) { let dbox = doc; // bcz: isButtonBar is intended to allow a collection of linear buttons to be dropped and nested into another collection of buttons... it's not being used yet, and isn't very elegant if (!doc.onDragStart && !doc.onClick && !doc.isButtonBar) { - const layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateField ? doc.layout : doc; + const layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc; if (layoutDoc.type === DocumentType.COL) { layoutDoc.isTemplateDoc = makeTemplate(layoutDoc); } else { diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 4dbf26956..1ffbd80ca 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -34,7 +34,7 @@ export function DocExtendableComponent<P extends DocExtendableProps, T>(schemaCt //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then @computed get Document(): T { return schemaCtor(this.props.Document); } @computed get layoutDoc() { return Doc.Layout(this.props.Document); } - @computed get dataDoc() { return (this.props.DataDoc && (this.props.Document.isTemplateField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : Doc.GetProto(this.props.Document)) as Doc; } + @computed get dataDoc() { return (this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : Doc.GetProto(this.props.Document)) as Doc; } @computed get extensionDoc() { return Doc.fieldExtensionDoc(this.dataDoc, this.props.fieldKey); } active = (outsideReaction?: boolean) => !this.props.Document.isBackground && (this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this.props.renderDepth === 0);// && !InkingControl.Instance.selectedTool; // bcz: inking state shouldn't affect static tools } @@ -58,7 +58,7 @@ export function DocAnnotatableComponent<P extends DocAnnotatableProps, T>(schema //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then @computed get Document(): T { return schemaCtor(this.props.Document); } @computed get layoutDoc() { return Doc.Layout(this.props.Document); } - @computed get dataDoc() { return (this.props.DataDoc && (this.props.Document.isTemplateField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : Doc.GetProto(this.props.Document)) as Doc; } + @computed get dataDoc() { return (this.props.DataDoc && (this.props.Document.isTemplateForField || this.props.Document.isTemplateDoc) ? this.props.DataDoc : Doc.GetProto(this.props.Document)) as Doc; } @computed get extensionDoc() { return Doc.fieldExtensionDoc(this.dataDoc, this.props.fieldKey); } @computed get extensionDocSync() { return Doc.fieldExtensionDocSync(this.dataDoc, this.props.fieldKey); } @computed get annotationsKey() { return "annotations"; } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 32fea15fb..322536b7e 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -369,7 +369,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> ruleProvider && heading && (Doc.GetProto(ruleProvider)["ruleRounding_" + heading] = `${Math.min(100, dist)}%`); usingRule = usingRule || (ruleProvider && heading ? true : false); }); - !usingRule && SelectionManager.SelectedDocuments().map(dv => dv.props.Document.layout instanceof Doc ? dv.props.Document.layout : dv.props.Document.isTemplateField ? dv.props.Document : Doc.GetProto(dv.props.Document)). + !usingRule && SelectionManager.SelectedDocuments().map(dv => dv.props.Document.layout instanceof Doc ? dv.props.Document.layout : dv.props.Document.isTemplateForField ? dv.props.Document : Doc.GetProto(dv.props.Document)). map(d => d.borderRounding = `${Math.min(100, dist)}%`); e.stopPropagation(); e.preventDefault(); diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index be07a9024..853d81a68 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -44,7 +44,7 @@ export class InkingControl { const oldColors = selected.map(view => { const targetDoc = view.props.Document.dragFactory instanceof Doc ? view.props.Document.dragFactory : view.props.Document.layout instanceof Doc ? view.props.Document.layout : - view.props.Document.isTemplateField ? view.props.Document : Doc.GetProto(view.props.Document); + view.props.Document.isTemplateForField ? view.props.Document : Doc.GetProto(view.props.Document); const sel = window.getSelection(); if (StrCast(targetDoc.layout).indexOf("FormattedTextBox") !== -1 && (!sel || sel.toString() !== "")) { targetDoc.color = this._selectedColor; diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 7fe42386a..b2e4b9d90 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -39,7 +39,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @observable _scroll = 0; // used to force the document decoration to update when scrolling @computed get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); } @computed get sectionFilter() { return StrCast(this.props.Document.sectionFilter); } - @computed get filteredChildren() { return this.childDocs.filter(d => !d.isMinimized).map(d => (Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d).layout as Doc) || d); } + @computed get filteredChildren() { return this.childDocs.filter(d => !d.isMinimized).map(d => (Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, d).layout as Doc) || d); } @computed get xMargin() { return NumCast(this.props.Document.xMargin, 2 * this.gridGap); } @computed get yMargin() { return Math.max(this.props.Document.showTitle && !this.props.Document.showTitleHover ? 30 : 0, NumCast(this.props.Document.yMargin, 2 * this.gridGap)); } @computed get gridGap() { return NumCast(this.props.Document.gridGap, 10); } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 9357b0507..6c4f940b6 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -73,7 +73,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { this.childDocs.map(async doc => !Doc.AreProtosEqual(args[1] as Doc, (await doc).layout as Doc) && Doc.ApplyTemplateTo(args[1] as Doc, (await doc), "layoutFromParent")); } else if (!(args[1] instanceof Promise)) { - this.childDocs.filter(d => !d.isTemplateField).map(async doc => doc.layoutKey === "layoutFromParent" && (doc.layoutKey = "layout")); + this.childDocs.filter(d => !d.isTemplateForField).map(async doc => doc.layoutKey === "layoutFromParent" && (doc.layoutKey = "layout")); } }); @@ -82,7 +82,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { this._childLayoutDisposer && this._childLayoutDisposer(); } - @computed get dataDoc() { return this.props.DataDoc && this.props.Document.isTemplateField ? Doc.GetProto(this.props.DataDoc) : Doc.GetProto(this.props.Document); } + @computed get dataDoc() { return this.props.DataDoc && this.props.Document.isTemplateForField ? Doc.GetProto(this.props.DataDoc) : Doc.GetProto(this.props.Document); } @computed get extensionDoc() { return Doc.fieldExtensionDoc(this.dataDoc, this.props.fieldKey); } // The data field for rendering this collection will be on the this.props.Document unless we're rendering a template in which case we try to use props.DataDoc. @@ -102,8 +102,8 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { } get childLayoutPairs(): { layout: Doc; data: Doc; }[] { - const { Document, DataDoc, fieldKey } = this.props; - const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, DataDoc, fieldKey, doc)).filter(pair => pair.layout); + const { Document, DataDoc } = this.props; + const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, DataDoc, doc)).filter(pair => pair.layout); return validPairs.map(({ data, layout }) => ({ data: data!, layout: layout! })); // this mapping is a bit of a hack to coerce types } get childDocList() { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 6b6fdff50..2c8c53f97 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -375,7 +375,7 @@ class TreeView extends React.Component<TreeViewProps> { if (this.props.onCheckedClick && this.props.document.type !== DocumentType.COL) { // this.props.document.treeViewChecked = this.props.document.treeViewChecked === "check" ? "x" : this.props.document.treeViewChecked === "x" ? undefined : "check"; ScriptCast(this.props.onCheckedClick).script.run({ - this: this.props.document.isTemplateField && this.props.dataDoc ? this.props.dataDoc : this.props.document, + this: this.props.document.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.props.document, heading: this.props.containingCollection.title, checked: this.props.document.treeViewChecked === "check" ? "x" : this.props.document.treeViewChecked === "x" ? undefined : "check", containingTreeView: this.props.treeViewId, @@ -519,7 +519,7 @@ class TreeView extends React.Component<TreeViewProps> { const rowWidth = () => panelWidth() - 20; return docs.map((child, i) => { - const pair = Doc.GetLayoutDataDocPair(containingCollection, dataDoc, key, child); + const pair = Doc.GetLayoutDataDocPair(containingCollection, dataDoc, child); if (!pair.layout || pair.data instanceof Promise) { return (null); } @@ -646,7 +646,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { ], { autoHeight: true, chromeStatus: "disabled", title: "detailed layout stack" }); detailedLayout.isTemplateDoc = makeTemplate(detailedLayout); - const cardLayout = ImageDocument(fallbackImg, { isTemplateDoc: true, isTemplateField: true }); // this acts like a template doc and a template field ... a little weird, but seems to work? + const cardLayout = ImageDocument(fallbackImg, { isTemplateDoc: true, isTemplateForField: "hero", }); // this acts like a template doc and a template field ... a little weird, but seems to work? cardLayout.proto!.layout = ImageBox.LayoutString("hero"); cardLayout.showTitle = "title"; cardLayout.showTitleHover = "titlehover"; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index a7e4fce4e..aa1559416 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -833,7 +833,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { this.Document.isRuleProvider && this.childLayoutPairs.map(pair => // iterate over the children of a displayed document (or if the displayed document is a template, iterate over the children of that template) DocListCast(Doc.Layout(pair.layout).data).map(heading => { - const headingPair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, heading); + const headingPair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, heading); const headingLayout = headingPair.layout && (pair.layout.data_ext instanceof Doc) && (pair.layout.data_ext[`Layout[${headingPair.layout[Id]}]`] as Doc) || headingPair.layout; if (headingLayout && NumCast(headingLayout.heading) > 0 && headingLayout.backgroundColor !== headingLayout.defaultBackgroundColor) { Doc.GetProto(this.props.Document)["ruleColor_" + NumCast(headingLayout.heading)] = headingLayout.backgroundColor; diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx index d29fe1711..ee48b47b7 100644 --- a/src/client/views/nodes/ButtonBox.tsx +++ b/src/client/views/nodes/ButtonBox.tsx @@ -36,7 +36,7 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt @computed get dataDoc() { return this.props.DataDoc && - (this.Document.isTemplateField || BoolCast(this.props.DataDoc.isTemplateField) || + (this.Document.isTemplateForField || BoolCast(this.props.DataDoc.isTemplateForField) || this.props.DataDoc.layout === this.props.Document) ? this.props.DataDoc : Doc.GetProto(this.props.Document); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 36f2e7a4d..b491acb8d 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -268,7 +268,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu SelectionManager.DeselectAll(); Doc.UnBrushDoc(this.props.Document); } else if (this.onClickHandler && this.onClickHandler.script) { - this.onClickHandler.script.run({ this: this.Document.isTemplateField && this.props.DataDoc ? this.props.DataDoc : this.props.Document, containingCollection: this.props.ContainingCollectionDoc }, console.log); + this.onClickHandler.script.run({ this: this.Document.isTemplateForField && this.props.DataDoc ? this.props.DataDoc : this.props.Document, containingCollection: this.props.ContainingCollectionDoc }, console.log); } else if (this.Document.type === DocumentType.BUTTON) { ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", e.clientX, e.clientY); } else if (this.props.Document.isButton === "Selector") { // this should be moved to an OnClick script @@ -438,7 +438,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu onPointerDown = (e: React.PointerEvent): void => { if (this.onPointerDownHandler && this.onPointerDownHandler.script) { - this.onPointerDownHandler.script.run({ this: this.Document.isTemplateField && this.props.DataDoc ? this.props.DataDoc : this.props.Document }, console.log); + this.onPointerDownHandler.script.run({ this: this.Document.isTemplateForField && this.props.DataDoc ? this.props.DataDoc : this.props.Document }, console.log); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointerup", this.onPointerUp); return; @@ -495,7 +495,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu onPointerUp = (e: PointerEvent): void => { if (this.onPointerUpHandler && this.onPointerUpHandler.script && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) { - this.onPointerUpHandler.script.run({ this: this.Document.isTemplateField && this.props.DataDoc ? this.props.DataDoc : this.props.Document }, console.log); + this.onPointerUpHandler.script.run({ this: this.Document.isTemplateForField && this.props.DataDoc ? this.props.DataDoc : this.props.Document }, console.log); document.removeEventListener("pointerup", this.onPointerUp); return; } @@ -996,7 +996,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu color: StrCast(this.Document.color), outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px", border: highlighting && borderRounding ? `${highlightStyles[fullDegree]} ${highlightColors[fullDegree]} ${localScale}px` : undefined, - boxShadow: this.props.Document.isTemplateField ? "black 0.2vw 0.2vw 0.8vw" : undefined, + boxShadow: this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : undefined, background: this.layoutDoc.type === DocumentType.FONTICON || this.layoutDoc.viewType === CollectionViewType.Linear ? undefined : backgroundColor, width: animwidth, height: animheight, diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 1cd5cdcea..3814f02da 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -1101,7 +1101,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this.layoutDoc.limitHeight = undefined; this.layoutDoc.autoHeight = false; } - const nh = this.Document.isTemplateField ? 0 : NumCast(this.dataDoc.nativeHeight, 0); + const nh = this.Document.isTemplateForField ? 0 : NumCast(this.dataDoc.nativeHeight, 0); const dh = NumCast(this.layoutDoc.height, 0); const newHeight = Math.max(10, (nh ? dh / nh * scrollHeight : scrollHeight) + (this.props.ChromeHeight ? this.props.ChromeHeight() : 0)); if (Math.abs(newHeight - dh) > 1) { // bcz: Argh! without this, we get into a React crash if the same document is opened in a freeform view and in the treeview. no idea why, but after dragging the freeform document, selecting it, and selecting text, it will compute to 1 pixel higher than the treeview which causes a cycle diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index e9f8e6429..669e7a72f 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -431,48 +431,49 @@ export namespace Doc { // // Determines whether the combination of the layoutDoc and dataDoc represents - // a template relationship. If so, the layoutDoc will be expanded into a new - // document that inherits the properties of the original layout while allowing - // for individual layout properties to be overridden in the expanded layout. + // a template relationship : there is a dataDoc and it doesn't match the layoutDoc an + // the lyouatDoc's layout is layout string (not a document) // export function WillExpandTemplateLayout(layoutDoc: Doc, dataDoc?: Doc) { - return BoolCast(layoutDoc.isTemplateField) && dataDoc && layoutDoc !== dataDoc && !(layoutDoc[StrCast(layoutDoc.layoutKey, "layout")] instanceof Doc); + return layoutDoc.isTemplateForField && dataDoc && layoutDoc !== dataDoc && !(Doc.LayoutField(layoutDoc) instanceof Doc); } // - // Returns an expanded template layout for a target data document. - // First it checks if an expanded layout already exists -- if so it will be stored on the dataDoc - // using the template layout doc's id as the field key. - // If it doesn't find the expanded layout, then it makes a delegate of the template layout and - // saves it on the data doc indexed by the template layout's id + // Returns an expanded template layout for a target data document if there is a template relationship + // between the two. If so, the layoutDoc is expanded into a new document that inherits the properties + // of the original layout while allowing for individual layout properties to be overridden in the expanded layout. // export function expandTemplateLayout(templateLayoutDoc: Doc, dataDoc?: Doc) { if (!WillExpandTemplateLayout(templateLayoutDoc, dataDoc) || !dataDoc) return templateLayoutDoc; - // if we have a data doc that doesn't match the layout, then we're rendering a template. - // ... which means we change the layout to be an expanded view of the template layout. - // This allows the view override the template's properties and be referenceable as its own document. + const templateField = StrCast(templateLayoutDoc.isTemplateForField); // the field that the template renders + const extensionDoc = fieldExtensionDoc(dataDoc, templateField); // an extension doc for the field that the template renders + // First it checks if an expanded layout already exists -- if so it will be stored on the dataDoc + // using the template layout doc's id as the field key. + // If it doesn't find the expanded layout, then it makes a delegate of the template layout and + // saves it on the data doc indexed by the template layout's id. + // const expandedLayoutFieldKey = "Layout[" + templateLayoutDoc[Id] + "]"; - const expandedTemplateLayout = dataDoc[expandedLayoutFieldKey]; - if (expandedTemplateLayout instanceof Doc) { - return expandedTemplateLayout; - } - if (expandedTemplateLayout === undefined) { - setTimeout(() => dataDoc[expandedLayoutFieldKey] === undefined && - (dataDoc[expandedLayoutFieldKey] = Doc.MakeDelegate(templateLayoutDoc, undefined, "[" + templateLayoutDoc.title + "]")), 0); + const expandedTemplateLayout = extensionDoc?.[expandedLayoutFieldKey]; + if (expandedTemplateLayout === undefined && extensionDoc) { + setTimeout(() => { + if (!extensionDoc[expandedLayoutFieldKey]) { + const newLayoutDoc = Doc.MakeDelegate(templateLayoutDoc, undefined, "[" + templateLayoutDoc.title + "]"); + extensionDoc[expandedLayoutFieldKey] = newLayoutDoc; + newLayoutDoc.resolvedDataDoc = dataDoc; + } + }, 0); } - return undefined; // use the templateLayout when it's not a template or the expandedTemplate is pending. + return expandedTemplateLayout instanceof Doc ? expandedTemplateLayout : undefined; // layout is undefined if the expandedTemplate is pending. } - export function GetLayoutDataDocPair(doc: Doc, dataDoc: Doc | undefined, fieldKey: string, childDocLayout: Doc) { - let layoutDoc: Doc | undefined = childDocLayout; - const resolvedDataDoc = !doc.isTemplateField && dataDoc !== doc && dataDoc ? Doc.GetDataDoc(dataDoc) : undefined; - if (resolvedDataDoc && Doc.WillExpandTemplateLayout(childDocLayout, resolvedDataDoc)) { - const extensionDoc = fieldExtensionDoc(resolvedDataDoc, StrCast(childDocLayout.templateField, StrCast(childDocLayout.title))); - layoutDoc = Doc.expandTemplateLayout(childDocLayout, extensionDoc !== resolvedDataDoc ? extensionDoc : undefined); - setTimeout(async () => layoutDoc && (layoutDoc.resolvedDataDoc = await resolvedDataDoc), 0); - } else layoutDoc = childDocLayout; - return { layout: layoutDoc, data: resolvedDataDoc }; + // returns the layout/data doc pair to render for the specified childDoc of a collection. + // The containerDoc is treated as a template if its containerDataDoc has a value. If so, + // the childDoc is treated as a layout description for some field of the container doc's data doc. + export function GetLayoutDataDocPair(containerDoc: Doc, containerDataDoc: Opt<Doc>, childDoc: Doc) { + const resolvedDataDoc = containerDoc.isTemplateForField || containerDataDoc === containerDoc || !containerDataDoc ? + undefined : Doc.GetDataDoc(containerDataDoc); + return { layout: Doc.expandTemplateLayout(childDoc, resolvedDataDoc), data: resolvedDataDoc }; } // @@ -483,6 +484,7 @@ export namespace Doc { // to store annotations, ink, and other data. // export function fieldExtensionDoc(doc: Doc, fieldKey: string) { + if (!fieldKey) return undefined; const extension = doc[fieldKey + "_ext"]; if (doc instanceof Doc && extension === undefined) { setTimeout(() => CreateDocumentExtensionForField(doc, fieldKey), 0); @@ -616,8 +618,7 @@ export namespace Doc { const metadataFieldKey = StrCast(templateField.title).replace(/^-/, ""); // update the original template to mark it as a template - templateField.templateField = metadataFieldKey; - templateField.isTemplateField = true; + templateField.isTemplateForField = metadataFieldKey; templateField.title = metadataFieldKey; // templateField.showTitle = suppressTitle ? undefined : "title"; diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts index 3683e5820..180c52b3d 100644 --- a/src/new_fields/documentSchemas.ts +++ b/src/new_fields/documentSchemas.ts @@ -26,7 +26,7 @@ export const documentSchema = createSchema({ dragFactory: Doc, // the document that serves as the "template" for the onDragStart script. ie, to drag out copies of the dragFactory document. ignoreAspect: "boolean", // whether aspect ratio should be ignored when laying out or manipulating the document autoHeight: "boolean", // whether the height of the document should be computed automatically based on its contents - isTemplateField: "boolean", // whether this document acts as a template layout for describing how other documents should be displayed + isTemplateForField: "string",// when specifies a field key, then the containing document is a template that renders the specified field isBackground: "boolean", // whether document is a background element and ignores input events (can only selet with marquee) type: "string", // enumerated type of document treeViewOpen: "boolean", // flag denoting whether the documents sub-tree (contents) is visible or hidden |