diff options
Diffstat (limited to 'src/client/views/collections')
6 files changed, 95 insertions, 98 deletions
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index cf39e26a8..33329d1ed 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -405,6 +405,7 @@ interface CollectionSchemaPreviewProps { renderDepth: number; width: () => number; height: () => number; + showOverlays?: (doc: Doc) => { title?: string, caption?: string }; CollectionView?: CollectionView | CollectionPDFView | CollectionVideoView; getTransform: () => Transform; addDocument: (document: Doc, allowDuplicates?: boolean) => boolean; @@ -488,6 +489,7 @@ export class CollectionSchemaPreview extends React.Component<CollectionSchemaPre fitToBox={this.props.fitToBox} renderDepth={this.props.renderDepth + 1} selectOnLoad={false} + showOverlays={this.props.showOverlays} addDocument={this.props.addDocument} removeDocument={this.props.removeDocument} moveDocument={this.props.moveDocument} diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index bc733f152..7e886304d 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -56,6 +56,9 @@ margin-left: -5; } + .collectionStackingView-columnDoc{ + display: inline-block; + } .collectionStackingView-columnDoc, .collectionStackingView-masonryDoc { diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 416c536f6..9266fc8fd 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -12,6 +12,8 @@ import "./CollectionStackingView.scss"; import { CollectionSubView } from "./CollectionSubView"; import { undoBatch } from "../../util/UndoManager"; import { DragManager } from "../../util/DragManager"; +import { DocTypes } from "../../documents/Documents"; +import { Transform } from "../../util/Transform"; @observer export class CollectionStackingView extends CollectionSubView(doc => doc) { @@ -19,6 +21,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { _draggerRef = React.createRef<HTMLDivElement>(); _heightDisposer?: IReactionDisposer; _gridSize = 1; + _docXfs: any[] = []; @computed get xMargin() { return NumCast(this.props.Document.xMargin, 2 * this.gridGap); } @computed get yMargin() { return NumCast(this.props.Document.yMargin, 2 * this.gridGap); } @computed get gridGap() { return NumCast(this.props.Document.gridGap, 10); } @@ -26,18 +29,11 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @computed get columnWidth() { return this.singleColumn ? (this.props.PanelWidth() / (this.props as any).ContentScaling() - 2 * this.xMargin) : Math.min(this.props.PanelWidth() - 2 * this.xMargin, NumCast(this.props.Document.columnWidth, 250)); } @computed get filteredChildren() { return this.childDocs.filter(d => !d.isMinimized); } - singleColDocHeight(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](); - } 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.singleColumn && (this.props.Document.height = this.filteredChildren.reduce((height, d, i) => - height + this.singleColDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap), this.yMargin)) + height + this.getDocHeight(d) + (i === this.filteredChildren.length - 1 ? this.yMargin : this.gridGap), this.yMargin)) , { fireImmediately: true }); } componentWillUnmount() { @@ -48,90 +44,86 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { moveDocument = (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean): boolean => { return this.props.removeDocument(doc) && addDocument(doc); } - getSingleDocTransform(doc: Doc, ind: number, width: number) { - let localY = this.filteredChildren.reduce((height, d, i) => - height + (i < ind ? this.singleColDocHeight(d) + this.gridGap : 0), this.yMargin); - let translate = this.props.ScreenToLocalTransform().inverse().transformPoint((this.props.PanelWidth() - width) / 2, localY); - let outerXf = Utils.GetScreenTransform(this._masonryGridRef!); - let offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translate[0], outerXf.translateY - translate[1]); - return this.props.ScreenToLocalTransform().translate(offset[0], offset[1]).scale(NumCast(doc.width, 1) / this.columnWidth); - } createRef = (ele: HTMLDivElement | null) => { this._masonryGridRef = ele; this.createDropTarget(ele!); } - @computed - get singleColumnChildren() { - return this.filteredChildren.map((d, i) => { - let layoutDoc = Doc.expandTemplateLayout(d, this.props.DataDoc); - let width = () => d.nativeWidth ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth; - let height = () => this.singleColDocHeight(layoutDoc); - let dxf = () => this.getSingleDocTransform(layoutDoc, i, width()).scale(this.columnWidth / d[WidthSym]()); - let gap = i === 0 ? 0 : this.gridGap; - return <div className="collectionStackingView-columnDoc" - key={d[Id]} - style={{ width: width(), display: "inline-block", marginTop: gap, height: `${height() / (this.props.Document[HeightSym]() - 2 * this.yMargin) * 100}%` }} > - <CollectionSchemaPreview - Document={layoutDoc} - DataDocument={d !== this.props.DataDoc ? this.props.DataDoc : undefined} - renderDepth={this.props.renderDepth} - width={width} - height={height} - getTransform={dxf} - CollectionView={this.props.CollectionView} - addDocument={this.props.addDocument} - moveDocument={this.props.moveDocument} - removeDocument={this.props.removeDocument} - active={this.props.active} - whenActiveChanged={this.props.whenActiveChanged} - addDocTab={this.props.addDocTab} - setPreviewScript={emptyFunction} - previewScript={undefined}> - </CollectionSchemaPreview> - </div>; - }); + overlays = (doc: Doc) => { + return doc.type === DocTypes.IMG ? { title: "title", caption: "caption" } : {}; } - getDocTransform(doc: Doc, dref: HTMLDivElement) { - let { scale, translateX, translateY } = Utils.GetScreenTransform(dref); + + getDisplayDoc(layoutDoc: Doc, d: Doc, dxf: () => Transform) { + let dataDoc = d !== this.props.DataDoc ? this.props.DataDoc : undefined; + let width = () => d.nativeWidth ? Math.min(layoutDoc[WidthSym](), this.columnWidth) : this.columnWidth; + let height = () => this.getDocHeight(layoutDoc); + let finalDxf = () => dxf().scale(this.columnWidth / layoutDoc[WidthSym]()); + return <CollectionSchemaPreview + Document={layoutDoc} + DataDocument={dataDoc} + showOverlays={this.overlays} + renderDepth={this.props.renderDepth} + width={width} + height={height} + getTransform={finalDxf} + CollectionView={this.props.CollectionView} + addDocument={this.props.addDocument} + moveDocument={this.props.moveDocument} + removeDocument={this.props.removeDocument} + active={this.props.active} + whenActiveChanged={this.props.whenActiveChanged} + addDocTab={this.props.addDocTab} + setPreviewScript={emptyFunction} + previewScript={undefined}> + </CollectionSchemaPreview>; + } + 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](); + } + + + offsetTransform(doc: Doc, translateX: number, translateY: number) { 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); } - docXfs: any[] = []; + 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]); + } + @computed get children() { - this.docXfs.length = 0; + this._docXfs.length = 0; return this.filteredChildren.map((d, i) => { - let aspect = d.nativeHeight ? NumCast(d.nativeWidth) / NumCast(d.nativeHeight) : undefined; - let dref = React.createRef<HTMLDivElement>(); - let dxf = () => this.getDocTransform(d, dref.current!).scale(this.columnWidth / d[WidthSym]()); - let width = () => d.nativeWidth ? Math.min(d[WidthSym](), this.columnWidth) : this.columnWidth; - let height = () => aspect ? width() / aspect : d[HeightSym](); - let rowSpan = Math.ceil((height() + this.gridGap) / (this._gridSize + 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}` }} > - <CollectionSchemaPreview - Document={d} - DataDocument={this.props.Document.layout instanceof Doc ? this.props.Document : this.props.DataDoc} - renderDepth={this.props.renderDepth} - CollectionView={this.props.CollectionView} - addDocument={this.props.addDocument} - moveDocument={this.props.moveDocument} - removeDocument={this.props.removeDocument} - getTransform={dxf} - width={width} - height={height} - active={this.props.active} - addDocTab={this.props.addDocTab} - whenActiveChanged={this.props.whenActiveChanged} - setPreviewScript={emptyFunction} - previewScript={undefined}> - </CollectionSchemaPreview> - </div>); + 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) { + let dxf = () => this.getSingleDocTransform(layoutDoc, i, width()); + let rowHgtPcnt = height() / (this.props.Document[HeightSym]() - 2 * this.yMargin) * 100; + 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._gridSize + 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>; + } }); } @@ -178,7 +170,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let targInd = -1; let where = [de.x, de.y]; if (de.data instanceof DragManager.DocumentDragData) { - this.docXfs.map((cd, i) => { + this._docXfs.map((cd, i) => { let pos = cd.dxf().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap); let pos1 = cd.dxf().inverse().transformPoint(cd.width(), cd.height()); if (where[0] > pos[0] && where[0] < pos1[0] && where[1] > pos[1] && where[1] < pos1[1]) { @@ -204,7 +196,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { onDrop = (e: React.DragEvent): void => { let where = [e.clientX, e.clientY]; let targInd = -1; - this.docXfs.map((cd, i) => { + this._docXfs.map((cd, i) => { let pos = cd.dxf().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap); let pos1 = cd.dxf().inverse().transformPoint(cd.width(), cd.height()); if (where[0] > pos[0] && where[0] < pos1[0] && where[1] > pos[1] && where[1] < pos1[1]) { @@ -241,7 +233,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { gridAutoRows: this.singleColumn ? undefined : `${this._gridSize}px` }} > - {this.singleColumn ? this.singleColumnChildren : this.children} + {this.children} {this.singleColumn ? (null) : this.columnDragger} </div> </div> diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index a7614b605..7e38fb0b2 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -102,7 +102,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) { } else if (de.data.moveDocument) { let movedDocs = de.data.options === this.props.Document[Id] ? de.data.draggedDocuments : de.data.droppedDocuments; added = movedDocs.reduce((added: boolean, d) => - de.data.moveDocument(d, this.props.Document, this.props.addDocument) || added, false); + de.data.moveDocument(d, this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.addDocument) || added, false); } else { added = de.data.droppedDocuments.reduce((added: boolean, d) => this.props.addDocument(d) || added, false); } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index ef340d770..e88f1a9d0 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -1,7 +1,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faAngleRight, faCamera, faExpand, faTrash, faBell, faCaretDown, faCaretRight, faCaretSquareDown, faCaretSquareRight, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, observable, trace } from "mobx"; +import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, HeightSym, WidthSym, Opt } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; @@ -73,9 +73,10 @@ class TreeView extends React.Component<TreeViewProps> { @observable _collapsed: boolean = true; @computed get fieldKey() { - let keys = Array.from(Object.keys(this.resolvedDataDoc)); + let keys = Array.from(Object.keys(this.resolvedDataDoc)); // bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set if (this.resolvedDataDoc.proto instanceof Doc) { - keys.push(...Array.from(Object.keys(this.resolvedDataDoc.proto))); + let arr = Array.from(Object.keys(this.resolvedDataDoc.proto));// bcz: Argh -- make untracked to avoid this rerunning whenever 'libraryBrush' is set + keys.push(...arr); while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1); } let keyList: string[] = []; @@ -113,12 +114,12 @@ class TreeView extends React.Component<TreeViewProps> { } } onPointerLeave = (e: React.PointerEvent): void => { - this.props.document.libraryBrush = false; + this.props.document.libraryBrush = undefined; this._header!.current!.className = "treeViewItem-header"; document.removeEventListener("pointermove", this.onDragMove, true); } onDragMove = (e: PointerEvent): void => { - this.props.document.libraryBrush = false; + this.props.document.libraryBrush = undefined; let x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); let rect = this._header!.current!.getBoundingClientRect(); let bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); @@ -203,7 +204,7 @@ class TreeView extends React.Component<TreeViewProps> { let onItemDown = SetupDrag(reference, () => this.resolvedDataDoc, this.move, this.props.dropAction, this.props.treeViewId, true); let headerElements = ( - <span className="collectionTreeView-keyHeader" key={this._chosenKey} + <span className="collectionTreeView-keyHeader" key={this._chosenKey + "chosen"} onPointerDown={action(() => { let ind = this.keyList.indexOf(this._chosenKey); ind = (ind + 1) % this.keyList.length; @@ -219,8 +220,8 @@ class TreeView extends React.Component<TreeViewProps> { return <> <div className="docContainer" id={`docContainer-${this.props.parentKey}`} ref={reference} onPointerDown={onItemDown} style={{ - background: BoolCast(this.props.document.libraryBrush, false) ? "#06121212" : "0", - outline: BoolCast(this.props.document.workspaceBrush, false) ? "dashed 1px #06123232" : undefined, + background: BoolCast(this.props.document.libraryBrush) ? "#06121212" : "0", + outline: BoolCast(this.props.document.workspaceBrush) ? "dashed 1px #06123232" : undefined, pointerEvents: this.props.active() || SelectionManager.GetIsDragging() ? "all" : "none" }} > @@ -354,7 +355,7 @@ class TreeView extends React.Component<TreeViewProps> { </ul >; } else { let layoutDoc = Doc.expandTemplateLayout(this.props.document, this.props.dataDoc); - contentElement = <div ref={this._dref} style={{ display: "inline-block", height: this.docHeight() }} key={this.props.document[Id]}> + contentElement = <div ref={this._dref} style={{ display: "inline-block", height: this.docHeight() }} key={this.props.document[Id] + this.props.document.title}> <CollectionSchemaPreview Document={layoutDoc} DataDocument={this.resolvedDataDoc} @@ -427,7 +428,7 @@ class TreeView extends React.Component<TreeViewProps> { dataDoc={dataDoc} containingCollection={containingCollection} treeViewId={treeViewId} - key={child[Id]} + key={child[Id] + "child " + i} indentDocument={indent} renderDepth={renderDepth} deleteDoc={remove} @@ -526,7 +527,6 @@ export class CollectionTreeView extends CollectionSubView(Document) { let dropAction = StrCast(this.props.Document.dropAction) as dropActionType; let addDoc = (doc: Doc, relativeTo?: Doc, before?: boolean) => Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, relativeTo, before); let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); - return !this.childDocs ? (null) : ( <div id="body" className="collectionTreeView-dropTarget" style={{ overflow: "auto" }} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 1777c287c..1867938a7 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -286,9 +286,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { // TODO This technically isn't correct if type !== "doc", as // currently nothing is done, but we should probably push a new state if (state.type === "doc" && panX !== undefined && panY !== undefined) { - const init = state.initializers[id]; + const init = state.initializers![id]; if (!init) { - state.initializers[id] = { + state.initializers![id] = { panX, panY }; HistoryUtil.pushState(state); @@ -302,7 +302,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { const newPanX = NumCast(doc.x) + NumCast(doc.width) / NumCast(doc.zoomBasis, 1) / 2; const newPanY = NumCast(doc.y) + NumCast(doc.height) / NumCast(doc.zoomBasis, 1) / 2; const newState = HistoryUtil.getState(); - newState.initializers[id] = { panX: newPanX, panY: newPanY }; + newState.initializers![id] = { panX: newPanX, panY: newPanY }; HistoryUtil.pushState(newState); this.setPan(newPanX, newPanY); @@ -501,7 +501,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`; const easing = () => this.props.Document.panTransformType === "Ease"; - if (this.props.fieldExt) Doc.UpdateDocumentExtensionForField(this.extensionDoc, this.props.fieldKey); + if (this.props.fieldExt) Doc.UpdateDocumentExtensionForField(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey); return ( <div className={containerName} ref={this.createDropTarget} onWheel={this.onPointerWheel} style={{ borderRadius: "inherit" }} |
