aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBob Zeleznik <zzzman@gmail.com>2020-01-22 22:04:46 -0500
committerBob Zeleznik <zzzman@gmail.com>2020-01-22 22:04:46 -0500
commitf970dd586c0914847b5a59951f586dad93a2cf04 (patch)
tree517970dd830acf1ca20cb5ca10fdc86b587ad639 /src
parent162cea3ee2167a6d999b99630c33edb3779c7bcc (diff)
streamling templates.
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts2
-rw-r--r--src/client/util/DropConverter.ts4
-rw-r--r--src/client/views/DocComponent.tsx4
-rw-r--r--src/client/views/DocumentDecorations.tsx2
-rw-r--r--src/client/views/InkingControl.tsx2
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx2
-rw-r--r--src/client/views/collections/CollectionSubView.tsx8
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx6
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx2
-rw-r--r--src/client/views/nodes/ButtonBox.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx8
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx2
-rw-r--r--src/new_fields/Doc.ts63
-rw-r--r--src/new_fields/documentSchemas.ts2
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