diff options
author | Tyler Schicke <tyler_schicke@brown.edu> | 2019-07-27 14:42:14 -0400 |
---|---|---|
committer | Tyler Schicke <tyler_schicke@brown.edu> | 2019-07-27 14:42:14 -0400 |
commit | e6df8eecb1191cb18f2ed326d5e0f512c47ebd96 (patch) | |
tree | d6ee28269fafef870ab5fb540f2a1be0db1c5457 | |
parent | c1377587f27044d89ec84befa9953de627d49873 (diff) | |
parent | 0d32cf945d610898d9ff993b5b7e9775e84da68d (diff) |
Merge branch 'master' of github-tsch-brown:browngraphicslab/Dash-Web
24 files changed, 150 insertions, 173 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 262194a40..32f728c71 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,16 +1,14 @@ -import { computed, observable, action } from 'mobx'; -import { DocumentView } from '../views/nodes/DocumentView'; -import { Doc, DocListCast, Opt } from '../../new_fields/Doc'; -import { FieldValue, Cast, NumCast, BoolCast, StrCast } from '../../new_fields/Types'; -import { listSpec } from '../../new_fields/Schema'; -import { undoBatch, UndoManager } from './UndoManager'; +import { action, computed, observable } from 'mobx'; +import { Doc } from '../../new_fields/Doc'; +import { Id } from '../../new_fields/FieldSymbols'; +import { BoolCast, Cast, NumCast } from '../../new_fields/Types'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; -import { CollectionView } from '../views/collections/CollectionView'; import { CollectionPDFView } from '../views/collections/CollectionPDFView'; import { CollectionVideoView } from '../views/collections/CollectionVideoView'; -import { Id } from '../../new_fields/FieldSymbols'; +import { CollectionView } from '../views/collections/CollectionView'; +import { DocumentView } from '../views/nodes/DocumentView'; import { LinkManager } from './LinkManager'; -import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; +import { undoBatch, UndoManager } from './UndoManager'; export class DocumentManager { diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 255855b45..c08a84742 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -533,7 +533,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> proto.nativeHeight = nheight = doc.height || 0; proto.ignoreAspect = true; } - if (nwidth > 0 && nheight > 0) { + if (nwidth > 0 && nheight > 0 && !BoolCast(proto.ignoreAspect)) { if (Math.abs(dW) > Math.abs(dH)) { if (!fixedAspect) { Doc.SetInPlace(element.props.Document, "nativeWidth", actualdW / (doc.width || 1) * (doc.nativeWidth || 0), true); @@ -553,7 +553,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } else { dW && (doc.width = actualdW); dH && (doc.height = actualdH); - Doc.SetInPlace(element.props.Document, "autoHeight", undefined, true); + dH && Doc.SetInPlace(element.props.Document, "autoHeight", undefined, true); } } }); diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index c66a92f48..7cabebddd 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -50,8 +50,10 @@ export class EditableView extends React.Component<EditableProps> { @action onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => { if (e.key === "Tab") { + e.stopPropagation(); this.props.OnTab && this.props.OnTab(); } else if (e.key === "Enter") { + e.stopPropagation(); if (!e.ctrlKey) { if (this.props.SetValue(e.currentTarget.value, e.shiftKey)) { this._editing = false; @@ -61,6 +63,7 @@ export class EditableView extends React.Component<EditableProps> { this._editing = false; } } else if (e.key === "Escape") { + e.stopPropagation(); this._editing = false; } } diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 7477c5b4f..5050f34ab 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -67,6 +67,7 @@ export default class KeyManager { } } MainView.Instance.toggleColorPicker(true); + SelectionManager.DeselectAll(); break; case "delete": case "backspace": diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 61a013963..8b7eb8856 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -7,7 +7,6 @@ import "normalize.css"; import * as React from 'react'; import { SketchPicker } from 'react-color'; import Measure from 'react-measure'; -import * as request from 'request'; import { Doc, DocListCast, Opt, HeightSym } from '../../new_fields/Doc'; import { Id } from '../../new_fields/FieldSymbols'; import { InkTool } from '../../new_fields/InkField'; @@ -407,7 +406,7 @@ export class MainView extends React.Component { </button> </div></li>)} <li key="undoTest"><button className="add-button round-button" title="Click if undo isn't working" onClick={() => UndoManager.TraceOpenBatches()}><FontAwesomeIcon icon="exclamation" size="sm" /></button></li> - <li key="color"><button className="add-button round-button" title="Select Color" onClick={() => this.toggleColorPicker()}><div className="toolbar-color-button" style={{ backgroundColor: InkingControl.Instance.selectedColor }} > + <li key="color"><button className="add-button round-button" title="Select Color" style={{ zIndex: 1000 }} onClick={() => this.toggleColorPicker()}><div className="toolbar-color-button" style={{ backgroundColor: InkingControl.Instance.selectedColor }} > <div className="toolbar-color-picker" onClick={this.onColorClick} style={this._colorPickerDisplay ? { color: "black", display: "block" } : { color: "black", display: "none" }}> <SketchPicker color={InkingControl.Instance.selectedColor} onChange={InkingControl.Instance.switchColor} /> </div> diff --git a/src/client/views/MetadataEntryMenu.tsx b/src/client/views/MetadataEntryMenu.tsx index bd5a307b3..c50e02f0d 100644 --- a/src/client/views/MetadataEntryMenu.tsx +++ b/src/client/views/MetadataEntryMenu.tsx @@ -76,6 +76,7 @@ export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{ onValueKeyDown = async (e: React.KeyboardEvent) => { if (e.key === "Enter") { + e.stopPropagation(); const script = KeyValueBox.CompileKVPScript(this._currentValue); if (!script) return; let doc = this.props.docs; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index ba7903419..0865058be 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -539,17 +539,17 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { } } + panelWidth = () => Math.min(this._panelWidth, Math.max(NumCast(this._document!.width), this.nativeWidth())); + panelHeight = () => Math.min(this._panelHeight, Math.max(NumCast(this._document!.height), NumCast(this._document!.nativeHeight, this._panelHeight))); + + nativeWidth = () => !BoolCast(this._document!.ignoreAspect) ? NumCast(this._document!.nativeWidth, this._panelWidth) : 0; + nativeHeight = () => !BoolCast(this._document!.ignoreAspect) ? NumCast(this._document!.nativeHeight, this._panelHeight) : 0; - nativeWidth = () => NumCast(this._document!.nativeWidth, this._panelWidth); - nativeHeight = () => { - let nh = NumCast(this._document!.nativeHeight, this._panelHeight); - let res = BoolCast(this._document!.ignoreAspect) ? this._panelHeight : nh; - return res; - } contentScaling = () => { const nativeH = this.nativeHeight(); const nativeW = this.nativeWidth(); - let wscale = this._panelWidth / nativeW; + if (!nativeW || !nativeH) return 1; + let wscale = this.panelWidth() / nativeW; return wscale * nativeH > this._panelHeight ? this._panelHeight / nativeH : wscale; } @@ -561,18 +561,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { } return Transform.Identity(); } - get scaleToFitMultiplier() { - let docWidth = NumCast(this._document!.width); - let docHeight = NumCast(this._document!.height); - if (NumCast(this._document!.nativeWidth) || !docWidth || !this._panelWidth || !this._panelHeight) return 1; - if (StrCast(this._document!.layout).indexOf("Collection") === -1 || - !BoolCast(this._document!.fitToContents, false) || - NumCast(this._document!.viewType) !== CollectionViewType.Freeform) return 1; - let scaling = Math.max(1, this._panelWidth / docWidth * docHeight > this._panelHeight ? - this._panelHeight / docHeight : this._panelWidth / docWidth); - return scaling; - } - get previewPanelCenteringOffset() { return (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2; } + get previewPanelCenteringOffset() { return this.nativeWidth && !BoolCast(this._document!.ignoreAspect) ? (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2 : 0; } addDocTab = (doc: Doc, dataDoc: Doc | undefined, location: string) => { if (doc.dockingConfig) { @@ -588,6 +577,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { return (null); } let resolvedDataDoc = this._document.layout instanceof Doc ? this._document : this._dataDoc; + console.log("pw = " + this.panelWidth() + "," + this.panelHeight() + " " + this.contentScaling()); return <DocumentView key={this._document[Id]} Document={this._document} DataDoc={resolvedDataDoc} @@ -595,8 +585,8 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { addDocument={undefined} removeDocument={undefined} ContentScaling={this.contentScaling} - PanelWidth={this.nativeWidth} - PanelHeight={this.nativeHeight} + PanelWidth={this.panelWidth} + PanelHeight={this.panelHeight} ScreenToLocalTransform={this.ScreenToLocalTransform} renderDepth={0} selectOnLoad={false} @@ -610,18 +600,15 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> { } @computed get content() { - if (!this._document) { - return (null); - } return ( <div className="collectionDockingView-content" ref={this._mainCont} - style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px) scale(${this.scaleToFitMultiplier})` }}> + style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px)` }}> {this.docView} </div >); } render() { - if (!this._isActive) return null; + if (!this._isActive || !this._document) return null; let theContent = this.content; return !this._document ? (null) : <Measure offset onResize={action((r: any) => { this._panelWidth = r.offset.width; this._panelHeight = r.offset.height; })}> diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 119aa7c19..0f67c47aa 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -11,7 +11,7 @@ import { Doc, DocListCast, DocListCastAsync, Field } from "../../../new_fields/D import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; -import { Cast, FieldValue, NumCast, StrCast, BoolCast } from "../../../new_fields/Types"; +import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; import { Docs } from "../../documents/Documents"; import { Gateway } from "../../northstar/manager/Gateway"; import { SetupDrag, DragManager } from "../../util/DragManager"; @@ -563,7 +563,7 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre height: "100%" }}> <DocumentView - DataDoc={this.props.Document.layout instanceof Doc ? this.props.Document : this.props.DataDocument} + DataDoc={this.props.DataDocument} Document={this.props.Document} fitToBox={this.props.fitToBox} renderDepth={this.props.renderDepth + 1} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 5a123bf65..dab03f052 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -46,14 +46,15 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { return fields; } componentDidMount() { - this._heightDisposer = reaction(() => [this.yMargin, this.gridGap, this.columnWidth, this.childDocs.map(d => [d.height, d.width, d.zoomBasis, d.nativeHeight, d.nativeWidth, d.isMinimized])], + this._heightDisposer = reaction(() => [this.yMargin, this.props.Document[WidthSym](), this.gridGap, this.columnWidth, this.childDocs.map(d => [d.height, d.width, d.zoomBasis, d.nativeHeight, d.nativeWidth, d.isMinimized])], () => { - if (this.singleColumn) { + if (this.singleColumn && BoolCast(this.props.Document.autoHeight)) { let hgt = this.Sections.size * 50 + this.filteredChildren.reduce((height, d, i) => { - let xhgt = height + this.getDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap); - return xhgt; + let pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d); + return height + this.getDocHeight(pair.layout) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap); }, this.yMargin); - this.layoutDoc.height = hgt; + (this.props.DataDoc && this.props.DataDoc.layout === this.layoutDoc ? this.props.DataDoc : this.layoutDoc) + .height = hgt * (this.props as any).ContentScaling(); } }, { fireImmediately: true }); } @@ -74,14 +75,12 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { return doc.type === DocumentType.IMG || doc.type === DocumentType.VID ? { title: "title", caption: "caption" } : {}; } - getDisplayDoc(layoutDoc: Doc, d: Doc, dxf: () => Transform) { - let resolvedDataDoc = !this.layoutDoc.isTemplate && this.props.DataDoc !== this.layoutDoc ? this.props.DataDoc : undefined; - let width = () => d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth; + getDisplayDoc(layoutDoc: Doc, dataDoc: Doc | undefined, dxf: () => Transform, width: () => number) { let height = () => this.getDocHeight(layoutDoc); let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]()); return <CollectionSchemaPreview Document={layoutDoc} - DataDocument={resolvedDataDoc} + DataDocument={dataDoc} showOverlays={this.overlays} renderDepth={this.props.renderDepth} fitToBox={true} @@ -102,51 +101,37 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { getDocHeight(d: Doc) { let nw = NumCast(d.nativeWidth); let nh = NumCast(d.nativeHeight); - let aspect = nw && nh ? nh / nw : 1; - let wid = Math.min(d[WidthSym](), this.columnWidth); - return (nw && nh) ? wid * aspect : d[HeightSym](); + if (!BoolCast(d.ignoreAspect) && nw && nh) { + let aspect = nw && nh ? nh / nw : 1; + let wid = Math.min(d[WidthSym](), this.columnWidth); + return wid * aspect; + } + return d[HeightSym](); } - offsetTransform(doc: Doc, translateX: number, translateY: number) { + getDocTransform(doc: Doc, dref: HTMLDivElement) { + let { scale, translateX, translateY } = Utils.GetScreenTransform(dref); let outerXf = Utils.GetScreenTransform(this._masonryGridRef!); let offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); return this.props.ScreenToLocalTransform().translate(offset[0], offset[1]).scale(NumCast(doc.width, 1) / this.columnWidth); } - getDocTransform(doc: Doc, dref: HTMLDivElement) { - let { scale, translateX, translateY } = Utils.GetScreenTransform(dref); - return this.offsetTransform(doc, translateX, translateY); - } - - getSingleDocTransform(doc: Doc, ind: number, width: number) { - let localY = this.filteredChildren.reduce((height, d, i) => - height + (i < ind ? this.getDocHeight(Doc.expandTemplateLayout(d, this.props.DataDoc)) + this.gridGap : 0), this.yMargin); - let translate = this.props.ScreenToLocalTransform().inverse().transformPoint((this.props.PanelWidth() - width) / 2, localY); - return this.offsetTransform(doc, translate[0], translate[1]); - } children(docs: Doc[]) { this._docXfs.length = 0; return docs.map((d, i) => { - let layoutDoc = Doc.expandTemplateLayout(d, this.props.DataDoc); - let width = () => d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth; - let height = () => this.getDocHeight(layoutDoc); - if (this.singleColumn) { - //have to add the height of all previous single column sections or the doc decorations will be in the wrong place. - let dxf = () => this.getSingleDocTransform(layoutDoc, i, width()); - let rowHgtPcnt = height(); - this._docXfs.push({ dxf: dxf, width: width, height: height }); - return <div className="collectionStackingView-columnDoc" key={d[Id]} style={{ width: width(), marginTop: i === 0 ? 0 : this.gridGap, height: `${rowHgtPcnt}` }} > - {this.getDisplayDoc(layoutDoc, d, dxf)} - </div>; - } else { - let dref = React.createRef<HTMLDivElement>(); - let dxf = () => this.getDocTransform(layoutDoc, dref.current!); - let rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap); - this._docXfs.push({ dxf: dxf, width: width, height: height }); - return <div className="collectionStackingView-masonryDoc" key={d[Id]} ref={dref} style={{ gridRowEnd: `span ${rowSpan}` }} > - {this.getDisplayDoc(layoutDoc, d, dxf)} - </div>; - } + let pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d) + let width = () => d.nativeWidth && !BoolCast(d.ignoreAspect) ? Math.min(pair.layout[WidthSym](), this.columnWidth) : this.columnWidth; + let height = () => this.getDocHeight(pair.layout); + let dref = React.createRef<HTMLDivElement>(); + let dxf = () => this.getDocTransform(pair.layout, dref.current!); + this._docXfs.push({ dxf: dxf, width: width, height: height }); + let rowHgtPcnt = height(); + let rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap); + let style = this.singleColumn ? { width: width(), marginTop: i === 0 ? 0 : this.gridGap, height: `${rowHgtPcnt}` } : { gridRowEnd: `span ${rowSpan}` }; + + return <div className={`collectionStackingView-${this.singleColumn ? "columnDoc" : "masonryDoc"}`} key={d[Id]} ref={dref} style={style} > + {this.getDisplayDoc(pair.layout, pair.data, dxf, width)} + </div>; }); } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 7781b26d9..cd137cd60 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -15,8 +15,6 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV import { CollectionSchemaView } from "./CollectionSchemaView"; import { CollectionStackingView } from './CollectionStackingView'; import { CollectionTreeView } from "./CollectionTreeView"; -import { StrCast, PromiseValue } from '../../../new_fields/Types'; -import { DocumentType } from '../../documents/Documents'; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index b546d1b78..6af87b138 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -21,10 +21,10 @@ export class CollectionFreeFormLinkView extends React.Component<CollectionFreeFo if (e.button === 0 && !InkingControl.Instance.selectedTool) { let a = this.props.A; let b = this.props.B; - let x1 = NumCast(a.x) + (BoolCast(a.isMinimized, false) ? 5 : a[WidthSym]() / 2); - let y1 = NumCast(a.y) + (BoolCast(a.isMinimized, false) ? 5 : a[HeightSym]() / 2); - let x2 = NumCast(b.x) + (BoolCast(b.isMinimized, false) ? 5 : b[WidthSym]() / 2); - let y2 = NumCast(b.y) + (BoolCast(b.isMinimized, false) ? 5 : b[HeightSym]() / 2); + let x1 = NumCast(a.x) + (BoolCast(a.isMinimized) ? 5 : a[WidthSym]() / 2); + let y1 = NumCast(a.y) + (BoolCast(a.isMinimized) ? 5 : a[HeightSym]() / 2); + let x2 = NumCast(b.x) + (BoolCast(b.isMinimized) ? 5 : b[WidthSym]() / 2); + let y2 = NumCast(b.y) + (BoolCast(b.isMinimized) ? 5 : b[HeightSym]() / 2); // this.props.LinkDocs.map(l => { // let width = l[WidthSym](); // l.x = (x1 + x2) / 2 - width / 2; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 1d6a907ce..35955942c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -61,11 +61,11 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { private inkKey = "ink"; get parentScaling() { - return (this.props as any).ContentScaling && this.Document.nativeWidth && this.fitToBox && !this.isAnnotationOverlay ? (this.props as any).ContentScaling() : 1; + return (this.props as any).ContentScaling && this.fitToBox && !this.isAnnotationOverlay ? (this.props as any).ContentScaling() : 1; } @computed get contentBounds() { - let bounds = this.fitToBox && !this.nativeWidth && !this.isAnnotationOverlay ? Doc.ComputeContentBounds(DocListCast(this.props.Document.data)) : undefined; + let bounds = this.fitToBox && !this.isAnnotationOverlay ? Doc.ComputeContentBounds(DocListCast(this.props.Document.data)) : undefined; return { panX: bounds ? (bounds.x + bounds.r) / 2 : this.Document.panX || 0, panY: bounds ? (bounds.y + bounds.b) / 2 : this.Document.panY || 0, @@ -370,24 +370,18 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { getChildDocumentViewProps(childDocLayout: Doc): DocumentViewProps { let self = this; - let resolvedDataDoc = !this.props.Document.isTemplate && this.props.DataDoc !== this.props.Document ? this.props.DataDoc : undefined; - let layoutDoc = childDocLayout; - if (resolvedDataDoc && Doc.WillExpandTemplateLayout(childDocLayout, resolvedDataDoc)) { - Doc.UpdateDocumentExtensionForField(resolvedDataDoc, this.props.fieldKey); - let fieldExtensionDoc = Doc.resolvedFieldDataDoc(resolvedDataDoc, StrCast(childDocLayout.templateField, StrCast(childDocLayout.title)), "dummy"); - layoutDoc = Doc.expandTemplateLayout(childDocLayout, fieldExtensionDoc !== resolvedDataDoc ? fieldExtensionDoc : undefined); - } else layoutDoc = Doc.expandTemplateLayout(childDocLayout, resolvedDataDoc); + let pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, childDocLayout); return { - DataDoc: resolvedDataDoc !== layoutDoc && resolvedDataDoc ? resolvedDataDoc : undefined, - Document: layoutDoc, + DataDoc: pair.data, + Document: pair.layout, addDocument: this.props.addDocument, removeDocument: this.props.removeDocument, moveDocument: this.props.moveDocument, ScreenToLocalTransform: this.getTransform, renderDepth: this.props.renderDepth + 1, - selectOnLoad: layoutDoc[Id] === this._selectOnLoaded, - PanelWidth: layoutDoc[WidthSym], - PanelHeight: layoutDoc[HeightSym], + selectOnLoad: pair.layout[Id] === this._selectOnLoaded, + PanelWidth: pair.layout[WidthSym], + PanelHeight: pair.layout[HeightSym], ContentScaling: returnOne, ContainingCollectionView: this.props.CollectionView, focus: this.focusDocument, @@ -477,7 +471,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { if (!(doc instanceof Doc)) return prev; var page = NumCast(doc.page, -1); if ((Math.abs(Math.round(page) - Math.round(curPage)) < 3) || page === -1) { - let minim = BoolCast(doc.isMinimized, false); + let minim = BoolCast(doc.isMinimized); if (minim === undefined || !minim) { const pos = script ? this.getCalculatedPositions(script, { doc, index: prev.length, collection: this.Document, docs, state }) : {}; state = pos.state === undefined ? state : pos.state; diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 389b9f68b..7ffd760e0 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -35,21 +35,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF @computed get zoom(): number { return 1 / FieldValue(this.Document.zoomBasis, 1); } @computed get nativeWidth(): number { return FieldValue(this.Document.nativeWidth, 0); } @computed get nativeHeight(): number { return FieldValue(this.Document.nativeHeight, 0); } - - set width(w: number) { - this.Document.width = w; - if (this.nativeWidth && this.nativeHeight) { - this.Document.height = this.nativeHeight / this.nativeWidth * w; - } - } - set height(h: number) { - this.Document.height = h; - if (this.nativeWidth && this.nativeHeight) { - this.Document.width = this.nativeWidth / this.nativeHeight * h; - } - } @computed get scaleToOverridingWidth() { return this.width / NumCast(this.props.Document.width, this.width); } - contentScaling = () => this.nativeWidth > 0 ? this.width / this.nativeWidth : 1; + + contentScaling = () => this.nativeWidth > 0 && !BoolCast(this.props.Document.ignoreAspect) ? this.width / this.nativeWidth : 1; panelWidth = () => this.props.PanelWidth(); panelHeight = () => this.props.PanelHeight(); getTransform = (): Transform => this.props.ScreenToLocalTransform() diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index bae0b5b96..bc2af2ae8 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -275,7 +275,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu let iconAnimating = Cast(maximizedDoc.isIconAnimating, List); if (!iconAnimating || (Date.now() - iconAnimating[2] > 1000)) { if (isMinimized === undefined) { - isMinimized = BoolCast(maximizedDoc.isMinimized, false); + isMinimized = BoolCast(maximizedDoc.isMinimized); } maximizedDoc.willMaximize = isMinimized; maximizedDoc.isMinimized = false; @@ -308,7 +308,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { SelectionManager.SelectDoc(this, e.ctrlKey); let isExpander = (e.target as any).id === "isExpander"; - if (BoolCast(this.props.Document.isButton, false) || isExpander) { + if (BoolCast(this.props.Document.isButton) || isExpander) { SelectionManager.DeselectAll(); let subBulletDocs = await DocListCastAsync(this.props.Document.subBulletDocs); let maximizedDocs = await DocListCastAsync(this.props.Document.maximizedDocs); @@ -326,7 +326,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu maxLocation = this.props.Document.maximizeLocation = (ctrlKey ? maxLocation : (maxLocation === "inPlace" || !maxLocation ? "inTab" : "inPlace")); if (!maxLocation || maxLocation === "inPlace") { let hadView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView); - let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !BoolCast(d.IsMinimized, false), false); + let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !BoolCast(d.IsMinimized), false); expandedDocs.forEach(maxDoc => Doc.GetProto(maxDoc).isMinimized = false); let hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView); if (!hasView) { @@ -409,7 +409,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu @undoBatch makeBtnClicked = (): void => { let doc = Doc.GetProto(this.props.Document); - doc.isButton = !BoolCast(doc.isButton, false); + doc.isButton = !BoolCast(doc.isButton); if (doc.isButton) { if (!doc.nativeWidth) { doc.nativeWidth = this.props.Document[WidthSym](); @@ -507,12 +507,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu @action freezeNativeDimensions = (): void => { let proto = this.props.Document.isTemplate ? this.props.Document : Doc.GetProto(this.props.Document); - if (proto.ignoreAspect === undefined && !proto.nativeWidth) { + this.props.Document.autoHeight = proto.autoHeight = false; + proto.ignoreAspect = !BoolCast(proto.ignoreAspect); + if (!BoolCast(proto.ignoreAspect) && !proto.nativeWidth) { proto.nativeWidth = this.props.PanelWidth(); proto.nativeHeight = this.props.PanelHeight(); - proto.ignoreAspect = true; } - proto.ignoreAspect = !BoolCast(proto.ignoreAspect, false); } @undoBatch @action @@ -546,7 +546,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu subitems.push({ description: "Open Right Alias", event: () => this.props.addDocTab && this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.dataDoc, "onRight"), icon: "caret-square-right" }); subitems.push({ description: "Open Fields", event: this.fieldsClicked, icon: "layer-group" }); cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" }); - cm.addItem({ description: BoolCast(this.props.Document.ignoreAspect, false) || !this.props.Document.nativeWidth || !this.props.Document.nativeHeight ? "Freeze" : "Unfreeze", event: this.freezeNativeDimensions, icon: "edit" }); + cm.addItem({ description: !BoolCast(this.props.Document.ignoreAspect) && this.props.Document.nativeWidth && this.props.Document.nativeHeight ? "Unfreeze" : "Freeze", event: this.freezeNativeDimensions, icon: "edit" }); cm.addItem({ description: "Pin to Pres", event: () => PresentationView.Instance.PinDoc(this.props.Document), icon: "map-pin" }); cm.addItem({ description: BoolCast(this.props.Document.lockedPosition) ? "Unlock Pos" : "Lock Pos", event: this.toggleLockPosition, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" }); cm.addItem({ description: "Make Background", event: this.makeBackground, icon: BoolCast(this.props.Document.lockedPosition) ? "unlock" : "lock" }); @@ -642,7 +642,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu let self = this; let backgroundColor = StrCast(this.layoutDoc.backgroundColor); let foregroundColor = StrCast(this.layoutDoc.color); - var nativeWidth = this.nativeWidth > 0 ? `${this.nativeWidth}px` : "100%"; + var nativeWidth = this.nativeWidth > 0 && !BoolCast(this.props.Document.ignoreAspect) ? `${this.nativeWidth}px` : "100%"; var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; let showOverlays = this.props.showOverlays ? this.props.showOverlays(this.layoutDoc) : undefined; let showTitle = showOverlays && showOverlays.title !== "undefined" ? showOverlays.title : StrCast(this.layoutDoc.showTitle); @@ -665,6 +665,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu outlineStyle: "dashed", outlineWidth: BoolCast(this.layoutDoc.libraryBrush) && !StrCast(Doc.GetProto(this.props.Document).borderRounding) ? `${this.props.ScreenToLocalTransform().Scale}px` : "0px", + marginLeft: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ? + `${-1 * this.props.ScreenToLocalTransform().Scale}px` : undefined, + marginTop: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ? + `${-1 * this.props.ScreenToLocalTransform().Scale}px` : undefined, border: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ? `dashed maroon ${this.props.ScreenToLocalTransform().Scale}px` : undefined, borderRadius: "inherit", diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 0a79677e2..bd0fd8301 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -459,8 +459,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe specificContextMenu = (e: React.MouseEvent): void => { let subitems: ContextMenuProps[] = []; subitems.push({ - description: BoolCast(this.props.Document.autoHeight, false) ? "Manual Height" : "Auto Height", - event: action(() => Doc.GetProto(this.props.Document).autoHeight = !BoolCast(this.props.Document.autoHeight, false)), icon: "expand-arrows-alt" + description: BoolCast(this.props.Document.autoHeight) ? "Manual Height" : "Auto Height", + event: action(() => Doc.GetProto(this.props.Document).autoHeight = !BoolCast(this.props.Document.autoHeight)), icon: "expand-arrows-alt" }); ContextMenu.Instance.addItem({ description: "Text Funcs...", subitems: subitems }); } diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx index d6ab2a34a..6f50033a4 100644 --- a/src/client/views/nodes/IconBox.tsx +++ b/src/client/views/nodes/IconBox.tsx @@ -64,7 +64,7 @@ export class IconBox extends React.Component<FieldViewProps> { let hideLabel = BoolCast(this.props.Document.hideLabel); let maxDocs = DocListCast(this.props.Document.maximizedDocs); let firstDoc = maxDocs.length ? maxDocs[0] : undefined; - let label = hideLabel ? "" : (firstDoc && labelField && !BoolCast(this.props.Document.useOwnTitle, false) ? firstDoc[labelField] : this.props.Document.title); + let label = hideLabel ? "" : (firstDoc && labelField && !BoolCast(this.props.Document.useOwnTitle) ? firstDoc[labelField] : this.props.Document.title); return ( <div className="iconBox-container" onContextMenu={this.specificContextMenu}> {this.minimizedIcon} diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index a942d6824..4aee3f68c 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -21,7 +21,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import "./ImageBox.scss"; import React = require("react"); import { RouteStore } from '../../../server/RouteStore'; -import { Docs } from '../../documents/Documents'; +import { Docs, DocumentType } from '../../documents/Documents'; import { DocServer } from '../../DocServer'; import { Font } from '@react-pdf/renderer'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -85,10 +85,20 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(this.dataDoc, this.props.fieldKey, "Alternates"); } @undoBatch + @action drop = (e: Event, de: DragManager.DropEvent) => { if (de.data instanceof DragManager.DocumentDragData) { de.data.droppedDocuments.forEach(action((drop: Doc) => { - if (de.mods === "AltKey" && /*this.dataDoc !== this.props.Document &&*/ drop.data instanceof ImageField) { + if (de.mods === "CtrlKey") { + let temp = Doc.MakeDelegate(drop); + this.props.Document.nativeWidth = Doc.GetProto(this.props.Document).nativeWidth = undefined; + this.props.Document.nativeHeight = Doc.GetProto(this.props.Document).nativeHeight = undefined; + this.props.Document.width = drop.width; + this.props.Document.height = drop.height; + Doc.GetProto(this.props.Document).type = DocumentType.TEMPLATE; + this.props.Document.layout = temp; + e.stopPropagation(); + } else if (de.mods === "AltKey" && /*this.dataDoc !== this.props.Document &&*/ drop.data instanceof ImageField) { Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new ImageField(drop.data.url); e.stopPropagation(); } else if (de.mods === "CtrlKey") { diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 9fc0f2080..77824b4ff 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -46,6 +46,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> { @action onEnterKey = (e: React.KeyboardEvent): void => { if (e.key === 'Enter') { + e.stopPropagation(); if (this._keyInput && this._valueInput && this.fieldDocToLayout) { if (KeyValueBox.SetField(this.fieldDocToLayout, this._keyInput, this._valueInput)) { this._keyInput = ""; @@ -153,7 +154,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> { <input style={{ width: "100%" }} type="text" value={this._keyInput} placeholder="Key" onChange={this.keyChanged} /> </td> <td className="keyValueBox-td-value" style={{ width: `${this.splitPercentage}%` }}> - <input style={{ width: "100%" }} type="text" value={this._valueInput} placeholder="Value" onChange={this.valueChanged} onKeyPress={this.onEnterKey} /> + <input style={{ width: "100%" }} type="text" value={this._valueInput} placeholder="Value" onChange={this.valueChanged} onKeyDown={this.onEnterKey} /> </td> </tr> ) diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx index a0c37a719..d4c92c9f2 100644 --- a/src/client/views/nodes/LinkMenuItem.tsx +++ b/src/client/views/nodes/LinkMenuItem.tsx @@ -7,7 +7,7 @@ import { undoBatch } from "../../util/UndoManager"; import './LinkMenu.scss'; import React = require("react"); import { Doc } from '../../../new_fields/Doc'; -import { StrCast, Cast, BoolCast, FieldValue, NumCast } from '../../../new_fields/Types'; +import { StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types'; import { observable, action } from 'mobx'; import { LinkManager } from '../../util/LinkManager'; import { DragLinkAsDocument } from '../../util/DragManager'; diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx index c9d442fe5..a6864e0f3 100644 --- a/src/client/views/pdf/Page.tsx +++ b/src/client/views/pdf/Page.tsx @@ -1,22 +1,18 @@ +import { action, IReactionDisposer, observable } from "mobx"; import { observer } from "mobx-react"; -import React = require("react"); -import { observable, action, runInAction, IReactionDisposer, reaction } from "mobx"; import * as Pdfjs from "pdfjs-dist"; -import { Opt, Doc, FieldResult, Field, DocListCast, WidthSym, HeightSym, DocListCastAsync } from "../../../new_fields/Doc"; -import "./PDFViewer.scss"; import "pdfjs-dist/web/pdf_viewer.css"; -import { PDFBox } from "../nodes/PDFBox"; -import { DragManager } from "../../util/DragManager"; -import { Docs, DocUtils } from "../../documents/Documents"; +import { Doc, DocListCastAsync, Opt, WidthSym } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; -import { emptyFunction } from "../../../Utils"; -import { Cast, NumCast, StrCast, BoolCast } from "../../../new_fields/Types"; import { listSpec } from "../../../new_fields/Schema"; -import { menuBar } from "prosemirror-menu"; -import { AnnotationTypes, PDFViewer, scale } from "./PDFViewer"; +import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; +import { Docs, DocUtils } from "../../documents/Documents"; +import { DragManager } from "../../util/DragManager"; +import { PDFBox } from "../nodes/PDFBox"; import PDFMenu from "./PDFMenu"; -import { UndoManager } from "../../util/UndoManager"; -import { copy } from "typescript-collections/dist/lib/arrays"; +import { scale } from "./PDFViewer"; +import "./PDFViewer.scss"; +import React = require("react"); interface IPageProps { diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx index 329630875..36f1178f1 100644 --- a/src/client/views/presentationview/PresentationElement.tsx +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -1,21 +1,19 @@ -import { observer } from "mobx-react"; -import React = require("react"); -import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; -import { NumCast, BoolCast, StrCast, Cast } from "../../../new_fields/Types"; -import { Id } from "../../../new_fields/FieldSymbols"; -import { observable, action, computed, runInAction } from "mobx"; -import "./PresentationView.scss"; -import { Utils } from "../../../Utils"; import { library } from '@fortawesome/fontawesome-svg-core'; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faFile as fileSolid, faFileDownload, faLocationArrow, faArrowUp, faSearch } from '@fortawesome/free-solid-svg-icons'; import { faFile as fileRegular } from '@fortawesome/free-regular-svg-icons'; +import { faArrowUp, faFile as fileSolid, faFileDownload, faLocationArrow, faSearch } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { action, computed, observable, runInAction } from "mobx"; +import { observer } from "mobx-react"; +import { Doc } from "../../../new_fields/Doc"; +import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; -import { DragManager, SetupDrag, dropActionType } from "../../util/DragManager"; +import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types"; +import { Utils } from "../../../Utils"; +import { DragManager, dropActionType, SetupDrag } from "../../util/DragManager"; import { SelectionManager } from "../../util/SelectionManager"; -import { indexOf } from "typescript-collections/dist/lib/arrays"; -import { map } from "bluebird"; +import "./PresentationView.scss"; +import React = require("react"); library.add(faArrowUp); library.add(fileSolid); diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx index f2fef7f16..e25725275 100644 --- a/src/client/views/presentationview/PresentationView.tsx +++ b/src/client/views/presentationview/PresentationView.tsx @@ -171,7 +171,7 @@ export class PresentationView extends React.Component<PresViewProps> { //storing the presentation status,ie. whether it was stopped or playing - let presStatusBackUp = BoolCast(this.curPresentation.presStatus, null); + let presStatusBackUp = BoolCast(this.curPresentation.presStatus); runInAction(() => this.presStatus = presStatusBackUp); } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 1a00db1c1..b5708e97b 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -389,11 +389,22 @@ export namespace Doc { } if (expandedTemplateLayout === undefined) { setTimeout(() => - dataDoc[expandedLayoutFieldKey] = Doc.MakeDelegate(templateLayoutDoc, undefined, "["+templateLayoutDoc.title + "]"), 0); + dataDoc[expandedLayoutFieldKey] = Doc.MakeDelegate(templateLayoutDoc, undefined, "[" + templateLayoutDoc.title + "]"), 0); } return templateLayoutDoc; // use the templateLayout when it's not a template or the expandedTemplate is pending. } + export function GetLayoutDataDocPair(doc: Doc, dataDoc: Doc | undefined, fieldKey: string, childDocLayout: Doc) { + let layoutDoc = childDocLayout; + let resolvedDataDoc = !doc.isTemplate && dataDoc !== doc ? dataDoc : undefined; + if (resolvedDataDoc && Doc.WillExpandTemplateLayout(childDocLayout, resolvedDataDoc)) { + Doc.UpdateDocumentExtensionForField(resolvedDataDoc, fieldKey); + let fieldExtensionDoc = Doc.resolvedFieldDataDoc(resolvedDataDoc, StrCast(childDocLayout.templateField, StrCast(childDocLayout.title)), "dummy"); + layoutDoc = Doc.expandTemplateLayout(childDocLayout, fieldExtensionDoc !== resolvedDataDoc ? fieldExtensionDoc : undefined); + } else layoutDoc = Doc.expandTemplateLayout(childDocLayout, resolvedDataDoc); + return { layout: layoutDoc, data: resolvedDataDoc }; + } + export function MakeCopy(doc: Doc, copyProto: boolean = false): Doc { const copy = new Doc; Object.keys(doc).forEach(key => { @@ -444,7 +455,7 @@ export namespace Doc { return otherdoc; } - export function MakeTemplate(fieldTemplate: Doc, metaKey: string, proto: Doc) { + export function MakeTemplate(fieldTemplate: Doc, metaKey: string, templateDataDoc: Doc) { // move data doc fields to layout doc as needed (nativeWidth/nativeHeight, data, ??) let backgroundLayout = StrCast(fieldTemplate.backgroundLayout); let fieldLayoutDoc = fieldTemplate; @@ -455,21 +466,24 @@ export namespace Doc { if (backgroundLayout) { backgroundLayout = backgroundLayout.replace(/fieldKey={"[^"]*"}/, `fieldKey={"${metaKey}"}`); } - let nw = Cast(fieldTemplate.nativeWidth, "number"); - let nh = Cast(fieldTemplate.nativeHeight, "number"); let layoutDelegate = fieldTemplate.layout instanceof Doc ? fieldLayoutDoc : fieldTemplate; layoutDelegate.layout = layout; - fieldTemplate.title = metaKey; fieldTemplate.templateField = metaKey; + fieldTemplate.title = metaKey; + fieldTemplate.isTemplate = true; fieldTemplate.layout = layoutDelegate !== fieldTemplate ? layoutDelegate : layout; fieldTemplate.backgroundLayout = backgroundLayout; - fieldTemplate.nativeWidth = nw; - fieldTemplate.nativeHeight = nh; - fieldTemplate.isTemplate = true; + /* move certain layout properties from the original data doc to the template layout to avoid + inheriting them from the template's data doc which may also define these fields for its own use. + */ + fieldTemplate.ignoreAspect = BoolCast(fieldTemplate.ignoreAspect); + fieldTemplate.singleColumn = BoolCast(fieldTemplate.singleColumn); + fieldTemplate.nativeWidth = Cast(fieldTemplate.nativeWidth, "number"); + fieldTemplate.nativeHeight = Cast(fieldTemplate.nativeHeight, "number"); fieldTemplate.showTitle = "title"; - setTimeout(() => fieldTemplate.proto = proto); + setTimeout(() => fieldTemplate.proto = templateDataDoc); } export async function ToggleDetailLayout(d: Doc) { diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts index f8a4a30b4..565ae2ee3 100644 --- a/src/new_fields/Types.ts +++ b/src/new_fields/Types.ts @@ -78,7 +78,7 @@ export function StrCast(field: FieldResult, defaultVal: string | null = "") { return Cast(field, "string", defaultVal); } -export function BoolCast(field: FieldResult, defaultVal: boolean | null = null) { +export function BoolCast(field: FieldResult, defaultVal: boolean | null = false) { return Cast(field, "boolean", defaultVal); } export function DateCast(field: FieldResult) { |