diff options
| author | bobzel <zzzman@gmail.com> | 2022-08-03 09:01:29 -0400 |
|---|---|---|
| committer | bobzel <zzzman@gmail.com> | 2022-08-03 09:01:29 -0400 |
| commit | 9c26b676be062f9bd0f1ab66f8ba40fc9ec85d42 (patch) | |
| tree | ba6f48f871ddc356fdf7fd51ce2465c6d9f80c69 /src/client/views/collections/CollectionStackingView.tsx | |
| parent | c1cd00c7664df694b867f4989a1f61d959390742 (diff) | |
| parent | 85dade366a9517796d1d80cee2be022d5cacdc93 (diff) | |
Merge branch 'master' into parker
Diffstat (limited to 'src/client/views/collections/CollectionStackingView.tsx')
| -rw-r--r-- | src/client/views/collections/CollectionStackingView.tsx | 520 |
1 files changed, 271 insertions, 249 deletions
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 632053df6..ff7594e5a 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -1,37 +1,36 @@ -import React = require("react"); -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { CursorProperty } from "csstype"; -import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; -import { observer } from "mobx-react"; -import { DataSym, Doc, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; -import { Id } from "../../../fields/FieldSymbols"; -import { List } from "../../../fields/List"; -import { listSpec } from "../../../fields/Schema"; -import { SchemaHeaderField } from "../../../fields/SchemaHeaderField"; -import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types"; -import { TraceMobx } from "../../../fields/util"; -import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, returnZero, setupMoveUpEvents, smoothScroll, Utils } from "../../../Utils"; -import { Docs, DocUtils } from "../../documents/Documents"; -import { DragManager, dropActionType } from "../../util/DragManager"; -import { SnappingManager } from "../../util/SnappingManager"; -import { Transform } from "../../util/Transform"; -import { undoBatch } from "../../util/UndoManager"; -import { ContextMenu } from "../ContextMenu"; -import { ContextMenuProps } from "../ContextMenuItem"; -import { EditableView } from "../EditableView"; -import { LightboxView } from "../LightboxView"; -import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; -import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment } from "../nodes/DocumentView"; -import { StyleProp } from "../StyleProvider"; -import { CollectionMasonryViewFieldRow } from "./CollectionMasonryViewFieldRow"; -import "./CollectionStackingView.scss"; -import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn"; -import { CollectionSubView } from "./CollectionSubView"; -import { CollectionViewType } from "./CollectionView"; -import { FieldViewProps } from "../nodes/FieldView"; -import { FormattedTextBox } from "../nodes/formattedText/FormattedTextBox"; -const _global = (window /* browser */ || global /* node */) as any; - +import React = require('react'); +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { CursorProperty } from 'csstype'; +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; +import { observer } from 'mobx-react'; +import { DataSym, Doc, HeightSym, Opt, WidthSym } from '../../../fields/Doc'; +import { Id } from '../../../fields/FieldSymbols'; +import { List } from '../../../fields/List'; +import { listSpec } from '../../../fields/Schema'; +import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; +import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; +import { TraceMobx } from '../../../fields/util'; +import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, returnZero, setupMoveUpEvents, smoothScroll, Utils } from '../../../Utils'; +import { Docs, DocUtils } from '../../documents/Documents'; +import { CollectionViewType } from '../../documents/DocumentTypes'; +import { DragManager, dropActionType } from '../../util/DragManager'; +import { SnappingManager } from '../../util/SnappingManager'; +import { Transform } from '../../util/Transform'; +import { undoBatch } from '../../util/UndoManager'; +import { ContextMenu } from '../ContextMenu'; +import { ContextMenuProps } from '../ContextMenuItem'; +import { EditableView } from '../EditableView'; +import { LightboxView } from '../LightboxView'; +import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView'; +import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment } from '../nodes/DocumentView'; +import { FieldViewProps } from '../nodes/FieldView'; +import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; +import { StyleProp } from '../StyleProvider'; +import { CollectionMasonryViewFieldRow } from './CollectionMasonryViewFieldRow'; +import './CollectionStackingView.scss'; +import { CollectionStackingViewFieldColumn } from './CollectionStackingViewFieldColumn'; +import { CollectionSubView } from './CollectionSubView'; +const _global = (window /* browser */ || global) /* node */ as any; export type collectionStackingViewProps = { chromeHidden?: boolean; @@ -115,11 +114,11 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection {this.getDisplayDoc(d, width)} </div>; }); - } + }; @action setDocHeight = (key: string, sectionHeight: number) => { this._heightMap.set(key, sectionHeight); - } + }; // is sections that all collections inherit? I think this is how we show the masonry/columns //TODO: this seems important @@ -128,7 +127,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection if (!this.pivotField || this.columnHeaders instanceof Promise) return new Map<SchemaHeaderField, Doc[]>(); if (this.columnHeaders === undefined) { - setTimeout(() => this.layoutDoc._columnHeaders = new List<SchemaHeaderField>(), 0); + setTimeout(() => (this.layoutDoc._columnHeaders = new List<SchemaHeaderField>()), 0); return new Map<SchemaHeaderField, Doc[]>(); } const columnHeaders = Array.from(this.columnHeaders); @@ -144,8 +143,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection const existingHeader = columnHeaders.find(sh => sh.heading === (castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`)); if (existingHeader) { fields.get(existingHeader)!.push(d); - } - else { + } else { const newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${this.pivotField.toUpperCase()} VALUE`); fields.set(newSchemaHeader, [d]); columnHeaders.push(newSchemaHeader); @@ -155,13 +153,19 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection // remove all empty columns if hideHeadings is set // we will want to have something like this, so that we can hide columns and add them back in if (this.layoutDoc._columnsHideIfEmpty) { - Array.from(fields.keys()).filter(key => !fields.get(key)!.length).map(header => { - fields.delete(header); - columnHeaders.splice(columnHeaders.indexOf(header), 1); - changed = true; - }); + Array.from(fields.keys()) + .filter(key => !fields.get(key)!.length) + .map(header => { + fields.delete(header); + columnHeaders.splice(columnHeaders.indexOf(header), 1); + changed = true; + }); } - changed && setTimeout(action(() => this.columnHeaders?.splice(0, this.columnHeaders.length, ...columnHeaders)), 0); + changed && + setTimeout( + action(() => this.columnHeaders?.splice(0, this.columnHeaders.length, ...columnHeaders)), + 0 + ); return fields; } @@ -171,14 +175,19 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection // reset section headers when a new filter is inputted this._pivotFieldDisposer = reaction( () => this.pivotField, - () => this.layoutDoc._columnHeaders = new List() + () => (this.layoutDoc._columnHeaders = new List()) + ); + this._autoHeightDisposer = reaction( + () => this.layoutDoc._autoHeight, + autoHeight => + autoHeight && + this.props.setHeight?.( + Math.min( + NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), + this.headerMargin + (this.isStackingView ? Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', '')))) : this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace('px', '')), 0)) + ) + ) ); - //TODO: where the heck are we getting filters from? - this._autoHeightDisposer = reaction(() => this.layoutDoc._autoHeight, - autoHeight => autoHeight && this.props.setHeight?.(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), - this.headerMargin + (this.isStackingView ? - Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace("px", "")))) : - this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0))))); } componentWillUnmount() { @@ -190,46 +199,51 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection @action moveDocument = (doc: Doc, targetCollection: Doc | undefined, addDocument: (document: Doc) => boolean): boolean => { return this.props.removeDocument?.(doc) && addDocument?.(doc) ? true : false; - } + }; createRef = (ele: HTMLDivElement | null) => { this._masonryGridRef = ele; this.createDashEventsTarget(ele!); //so the whole grid is the drop target? - } + }; - @computed get onChildClickHandler() { return () => this.props.childClickScript || ScriptCast(this.Document.onChildClick); } - @computed get onChildDoubleClickHandler() { return () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick); } + @computed get onChildClickHandler() { + return () => this.props.childClickScript || ScriptCast(this.Document.onChildClick); + } + @computed get onChildDoubleClickHandler() { + return () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick); + } addDocTab = (doc: Doc, where: string) => { - if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) { + if (where === 'inPlace' && this.layoutDoc.isInPlaceContainer) { this.dataDoc[this.props.fieldKey] = new List<Doc>([doc]); return true; } return this.props.addDocTab(doc, where); - } + }; scrollToBottom = () => { smoothScroll(500, this._mainCont!, this._mainCont!.scrollHeight); - } + }; // let's dive in and get the actual document we want to drag/move around focusDocument = (doc: Doc, options?: DocFocusOptions) => { Doc.BrushDoc(doc); let focusSpeed = 0; - const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName("documentView-node")).find((node: any) => node.id === doc[Id]); + const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]); if (found) { const top = found.getBoundingClientRect().top; const localTop = this.props.ScreenToLocalTransform().transformPoint(0, top); if (Math.floor(localTop[1]) !== 0) { - smoothScroll(focusSpeed = doc.presTransition || doc.presTransition === 0 ? NumCast(doc.presTransition) : 500, this._mainCont!, localTop[1] + this._mainCont!.scrollTop); + smoothScroll((focusSpeed = doc.presTransition || doc.presTransition === 0 ? NumCast(doc.presTransition) : 500), this._mainCont!, localTop[1] + this._mainCont!.scrollTop); } } - const endFocus = async (moved: boolean) => options?.afterFocus ? options?.afterFocus(moved) : ViewAdjustment.doNothing; + const endFocus = async (moved: boolean) => options?.afterFocus?.(moved) ?? ViewAdjustment.doNothing; this.props.focus(this.rootDoc, { - willZoom: options?.willZoom, scale: options?.scale, afterFocus: (didFocus: boolean) => - new Promise<ViewAdjustment>(res => setTimeout(async () => res(await endFocus(didFocus)), focusSpeed)) + willZoom: options?.willZoom, + scale: options?.scale, + afterFocus: (didFocus: boolean) => new Promise<ViewAdjustment>(res => setTimeout(async () => res(await endFocus(didFocus)), focusSpeed)), }); - } + }; styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string) => { if (property === StyleProp.Opacity && doc) { @@ -241,33 +255,33 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection } } return this.props.styleProvider?.(doc, props, property); - } + }; @undoBatch @action onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => { const docView = fieldProps.DocumentView?.(); - if (docView && ["Enter"].includes(e.key) && e.ctrlKey) { + if (docView && ['Enter'].includes(e.key) && e.ctrlKey) { e.stopPropagation?.(); - const below = !e.altKey && e.key !== "Tab"; + const below = !e.altKey && e.key !== 'Tab'; const layoutKey = StrCast(docView.LayoutFieldKey); const newDoc = Doc.MakeCopy(docView.rootDoc, true); const dataField = docView.rootDoc[Doc.LayoutFieldKey(newDoc)]; newDoc[DataSym][Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List<Doc>([]) : undefined; - if (layoutKey !== "layout" && docView.rootDoc[layoutKey] instanceof Doc) { + if (layoutKey !== 'layout' && docView.rootDoc[layoutKey] instanceof Doc) { newDoc[layoutKey] = docView.rootDoc[layoutKey]; } Doc.GetProto(newDoc).text = undefined; FormattedTextBox.SelectOnLoad = newDoc[Id]; return this.addDocument?.(newDoc); } - } + }; isContentActive = () => this.props.isSelected() || this.props.isContentActive(); isChildContentActive = () => this.props.isDocumentActive?.() && (this.props.childDocumentsActive?.() || BoolCast(this.rootDoc.childDocumentsActive)); // this is what renders the document that you see on the screen // called in Children: this actually adds a document to our children list getDisplayDoc(doc: Doc, width: () => number) { - const dataDoc = (!doc.isTemplateDoc && !doc.isTemplateForField && !doc.PARAMS) ? undefined : this.props.DataDoc; + const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField && !doc.PARAMS ? undefined : this.props.DataDoc; const height = () => this.getDocHeight(doc); let dref: Opt<DocumentView>; @@ -291,8 +305,8 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection NativeWidth={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || doc._fitWidth && !Doc.NativeWidth(doc) ? width : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox NativeHeight={this.props.childIgnoreNativeSize ? returnZero : this.props.childFitWidth?.(doc) || doc._fitWidth && !Doc.NativeHeight(doc) ? height : undefined} dontCenter={this.props.childIgnoreNativeSize ? "xy" : undefined} - dontRegisterView={dataDoc ? true : BoolCast(this.layoutDoc.childDontRegisterViews, this.props.dontRegisterView)} - rootSelected={this.rootSelected} + dontRegisterView={BoolCast(this.layoutDoc.childDontRegisterViews, this.props.dontRegisterView)} // used to be true if DataDoc existed, but template textboxes won't autoHeight resize if dontRegisterView is set, but they need to. + rootSelected={this.rootSelected} showTitle={this.props.childShowTitle} dropAction={StrCast(this.layoutDoc.childDropAction) as dropActionType} onClick={this.onChildClickHandler} @@ -322,8 +336,8 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection getDocTransform(doc: Doc, dref?: DocumentView) { const y = this._scroll; // required for document decorations to update when the text box container is scrolled const { scale, translateX, translateY } = Utils.GetScreenTransform(dref?.ContentDiv || undefined); - // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off - return new Transform(- translateX + (dref?.centeringX || 0), - translateY + (dref?.centeringY || 0), 1).scale(this.props.ScreenToLocalTransform().Scale); + // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off + return new Transform(-translateX + (dref?.centeringX || 0), -translateY + (dref?.centeringY || 0), 1).scale(this.props.ScreenToLocalTransform().Scale); } getDocWidth(d?: Doc) { if (!d) return 0; @@ -343,38 +357,43 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection getDocHeight(d?: Doc) { if (!d || d.hidden) return 0; const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.()); - const childDataDoc = (!d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS) ? undefined : this.props.DataDoc; - const maxHeight = (lim => lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim)(NumCast(this.layoutDoc.childLimitHeight, -1)); + const childDataDoc = !d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS ? undefined : this.props.DataDoc; + const maxHeight = (lim => (lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim))(NumCast(this.layoutDoc.childLimitHeight, -1)); const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[WidthSym]() : 0); const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!(childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? d[HeightSym]() : 0); if (nw && nh) { const colWid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1); const docWid = this.layoutDoc._columnsFill ? colWid : Math.min(this.getDocWidth(d), colWid); - return Math.min( - maxHeight, - docWid * nh / nw); + return Math.min(maxHeight, (docWid * nh) / nw); } const childHeight = NumCast(childLayoutDoc._height); - const panelHeight = (childLayoutDoc._fitWidth || this.props.childFitWidth?.(d)) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin; + const panelHeight = childLayoutDoc._fitWidth || this.props.childFitWidth?.(d) ? Number.MAX_SAFE_INTEGER : this.props.PanelHeight() - 2 * this.yMargin; return Math.min(childHeight, maxHeight, panelHeight); } // This following three functions must be from the view Mehek showed columnDividerDown = (e: React.PointerEvent) => { - runInAction(() => this._cursor = "grabbing"); - setupMoveUpEvents(this, e, this.onDividerMove, action(() => this._cursor = "grab"), emptyFunction); - } + runInAction(() => (this._cursor = 'grabbing')); + setupMoveUpEvents( + this, + e, + this.onDividerMove, + action(() => (this._cursor = 'grab')), + emptyFunction + ); + }; @action onDividerMove = (e: PointerEvent, down: number[], delta: number[]) => { this.layoutDoc._columnWidth = Math.max(10, this.columnWidth + delta[0]); return false; - } + }; @computed get columnDragger() { - return <div className="collectionStackingView-columnDragger" onPointerDown={this.columnDividerDown} ref={this._draggerRef} - style={{ cursor: this._cursor, left: `${this.columnWidth + this.xMargin}px`, top: `${Math.max(0, this.yMargin - 9)}px` }} > - <FontAwesomeIcon icon={"arrows-alt-h"} /> - </div>; + return ( + <div className="collectionStackingView-columnDragger" onPointerDown={this.columnDividerDown} ref={this._draggerRef} style={{ cursor: this._cursor, left: `${this.columnWidth + this.xMargin}px`, top: `${Math.max(0, this.yMargin - 9)}px` }}> + <FontAwesomeIcon icon={'arrows-alt-h'} /> + </div> + ); } // TODO: plj @@ -418,7 +437,10 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection if (de.complete.docDragData) { // going to re-add the docs to the _docXFs based on position of where we just dropped this._docXfs.map((cd, i) => { - const pos = cd.stackedDocTransform().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap); + const pos = cd + .stackedDocTransform() + .inverse() + .transformPoint(-2 * this.gridGap, -2 * this.gridGap); const pos1 = cd.stackedDocTransform().inverse().transformPoint(cd.width(), cd.height()); if (where[0] > pos[0] && where[0] < pos1[0] && where[1] > pos[1] && (i === this._docXfs.length - 1 || where[1] < pos1[1])) { dropInd = i; @@ -438,21 +460,19 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection // still figuring out where to add the document if (docs && newDocs.length) { const insertInd = dropInd === -1 ? docs.length : dropInd + dropAfter; - const offset = newDocs.reduce((off, ndoc) => this.filteredChildren.find((fdoc, i) => ndoc === fdoc && i < insertInd) ? off + 1 : off, 0); + const offset = newDocs.reduce((off, ndoc) => (this.filteredChildren.find((fdoc, i) => ndoc === fdoc && i < insertInd) ? off + 1 : off), 0); newDocs.filter(ndoc => docs.indexOf(ndoc) !== -1).forEach(ndoc => docs.splice(docs.indexOf(ndoc), 1)); docs.splice(insertInd - offset, 0, ...newDocs); } } - } // it seems like we're creating a link here. Weird. I didn't know that you could establish links by dragging - else if (de.complete.linkDragData?.dragDocument.context === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) { - const source = Docs.Create.TextDocument("", { _width: 200, _height: 75, _fitWidth: true, title: "dropped annotation" }); + } else if (de.complete.linkDragData?.dragDocument.context === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) { + const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _fitWidth: true, title: 'dropped annotation' }); this.props.addDocument?.(source); - de.complete.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: de.complete.linkDragData.linkSourceGetAnchor() }, "doc annotation", ""); // TODODO this is where in text links get passed + de.complete.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: de.complete.linkDragData.linkSourceGetAnchor() }, 'doc annotation', ''); // TODODO this is where in text links get passed e.stopPropagation(); - } - else if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de.complete.annoDragData); + } else if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de.complete.annoDragData); return false; - } + }; @undoBatch internalAnchorAnnoDrop(e: Event, annoDragData: DragManager.AnchorAnnoDragData) { @@ -473,7 +493,10 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection const where = [e.clientX, e.clientY]; let targInd = -1; this._docXfs.map((cd, i) => { - const pos = cd.stackedDocTransform().inverse().transformPoint(-2 * this.gridGap, -2 * this.gridGap); + const pos = cd + .stackedDocTransform() + .inverse() + .transformPoint(-2 * this.gridGap, -2 * this.gridGap); const pos1 = cd.stackedDocTransform().inverse().transformPoint(cd.width(), cd.height()); if (where[0] > pos[0] && where[0] < pos1[0] && where[1] > pos[1] && where[1] < pos1[1]) { targInd = i; @@ -489,102 +512,105 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection } } }); - } - // sections are important + }; headings = () => Array.from(this.Sections); refList: any[] = []; // what a section looks like if we're in stacking view sectionStacking = (heading: SchemaHeaderField | undefined, docList: Doc[]) => { const key = this.pivotField; - let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined; + let type: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | undefined = undefined; if (this.pivotField) { const types = docList.length ? docList.map(d => typeof d[key]) : this.filteredChildren.map(d => typeof d[key]); if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) { type = types[0]; } } - //TODO: I think that we only have one of these atm - return <CollectionStackingViewFieldColumn - unobserveHeight={ref => this.refList.splice(this.refList.indexOf(ref), 1)} - observeHeight={ref => { - if (ref) { - this.refList.push(ref); - this.observer = new _global.ResizeObserver(action((entries: any) => { - if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { - const height = this.headerMargin + - Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), - Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace("px", ""))))); - if (!LightboxView.IsLightboxDocView(this.props.docViewPath())) { - this.props.setHeight?.(height); - } - } - })); - this.observer.observe(ref); - } - }} - addDocument={this.addDocument} - chromeHidden={this.chromeHidden} - columnHeaders={this.columnHeaders} - Document={this.props.Document} - DataDoc={this.props.DataDoc} - renderChildren={this.children} - columnWidth={this.columnWidth} - numGroupColumns={this.numGroupColumns} - gridGap={this.gridGap} - pivotField={this.pivotField} - key={heading?.heading ?? ""} - headings={this.headings} - heading={heading?.heading ?? ""} - headingObject={heading} - docList={docList} - yMargin={this.yMargin} - type={type} - createDropTarget={this.createDashEventsTarget} - screenToLocalTransform={this.props.ScreenToLocalTransform} - />; - } + return ( + <CollectionStackingViewFieldColumn + unobserveHeight={ref => this.refList.splice(this.refList.indexOf(ref), 1)} + observeHeight={ref => { + if (ref) { + this.refList.push(ref); + this.observer = new _global.ResizeObserver( + action((entries: any) => { + if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { + const height = this.headerMargin + Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', ''))))); + if (!LightboxView.IsLightboxDocView(this.props.docViewPath())) { + this.props.setHeight?.(height); + } + } + }) + ); + this.observer.observe(ref); + } + }} + addDocument={this.addDocument} + chromeHidden={this.chromeHidden} + columnHeaders={this.columnHeaders} + Document={this.props.Document} + DataDoc={this.props.DataDoc} + renderChildren={this.children} + columnWidth={this.columnWidth} + numGroupColumns={this.numGroupColumns} + gridGap={this.gridGap} + pivotField={this.pivotField} + key={heading?.heading ?? ''} + headings={this.headings} + heading={heading?.heading ?? ''} + headingObject={heading} + docList={docList} + yMargin={this.yMargin} + type={type} + createDropTarget={this.createDashEventsTarget} + screenToLocalTransform={this.props.ScreenToLocalTransform} + /> + ); + }; // what a section looks like if we're in masonry. Shouldn't actually need to use this. sectionMasonry = (heading: SchemaHeaderField | undefined, docList: Doc[], first: boolean) => { const key = this.pivotField; - let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined; + let type: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | undefined = undefined; const types = docList.length ? docList.map(d => typeof d[key]) : this.filteredChildren.map(d => typeof d[key]); if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) { type = types[0]; } - const rows = () => !this.isStackingView ? 1 : Math.max(1, Math.min(docList.length, - Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap)))); - return <CollectionMasonryViewFieldRow - showHandle={first} - Document={this.props.Document} - chromeHidden={this.chromeHidden} - pivotField={this.pivotField} - unobserveHeight={(ref) => this.refList.splice(this.refList.indexOf(ref), 1)} - observeHeight={(ref) => { - if (ref) { - this.refList.push(ref); - this.observer = new _global.ResizeObserver(action((entries: any) => { - if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { - const height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace("px", "")), 0); - this.props.setHeight?.(this.headerMargin + height); - } - })); - this.observer.observe(ref); - } - }} - key={heading ? heading.heading : ""} - rows={rows} - headings={this.headings} - heading={heading ? heading.heading : ""} - headingObject={heading} - docList={docList} - parent={this} - type={type} - createDropTarget={this.createDashEventsTarget} - screenToLocalTransform={this.props.ScreenToLocalTransform} - setDocHeight={this.setDocHeight} - />; - } + const rows = () => (!this.isStackingView ? 1 : Math.max(1, Math.min(docList.length, Math.floor((this.props.PanelWidth() - 2 * this.xMargin) / (this.columnWidth + this.gridGap))))); + return ( + <CollectionMasonryViewFieldRow + showHandle={first} + Document={this.props.Document} + chromeHidden={this.chromeHidden} + pivotField={this.pivotField} + unobserveHeight={ref => this.refList.splice(this.refList.indexOf(ref), 1)} + observeHeight={ref => { + if (ref) { + this.refList.push(ref); + this.observer = new _global.ResizeObserver( + action((entries: any) => { + if (this.layoutDoc._autoHeight && ref && this.refList.length && !SnappingManager.GetIsDragging()) { + const height = this.refList.reduce((p, r) => p + Number(getComputedStyle(r).height.replace('px', '')), 0); + this.props.setHeight?.(this.headerMargin + height); + } + }) + ); + this.observer.observe(ref); + } + }} + key={heading ? heading.heading : ''} + rows={rows} + headings={this.headings} + heading={heading ? heading.heading : ''} + headingObject={heading} + docList={docList} + parent={this} + type={type} + createDropTarget={this.createDashEventsTarget} + screenToLocalTransform={this.props.ScreenToLocalTransform} + setDocHeight={this.setDocHeight} + /> + ); + }; @action // What are we adding a group to? @@ -595,25 +621,25 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection return true; } return false; - } + }; sortFunc = (a: [SchemaHeaderField, Doc[]], b: [SchemaHeaderField, Doc[]]): 1 | -1 => { - const descending = StrCast(this.layoutDoc._columnsSort) === "descending"; + const descending = StrCast(this.layoutDoc._columnsSort) === 'descending'; const firstEntry = descending ? b : a; const secondEntry = descending ? a : b; return firstEntry[0].heading > secondEntry[0].heading ? 1 : -1; - } + }; onContextMenu = (e: React.MouseEvent): void => { // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout if (!e.isPropagationStopped()) { const subItems: ContextMenuProps[] = []; - subItems.push({ description: `${this.layoutDoc._columnsFill ? "Variable Size" : "Autosize"} Column`, event: () => this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill, icon: "plus" }); - subItems.push({ description: `${this.layoutDoc._autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight, icon: "plus" }); - subItems.push({ description: "Clear All", event: () => this.dataDoc.data = new List([]), icon: "times" }); - ContextMenu.Instance.addItem({ description: "Options...", subitems: subItems, icon: "eye" }); + subItems.push({ description: `${this.layoutDoc._columnsFill ? 'Variable Size' : 'Autosize'} Column`, event: () => (this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill), icon: 'plus' }); + subItems.push({ description: `${this.layoutDoc._autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight), icon: 'plus' }); + subItems.push({ description: 'Clear All', event: () => (this.dataDoc.data = new List([])), icon: 'times' }); + ContextMenu.Instance.addItem({ description: 'Options...', subitems: subItems, icon: 'eye' }); } - } + }; // @computed get renderedSections() { @@ -623,8 +649,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection const entries = Array.from(this.Sections.entries()); sections = this.layoutDoc._columnsSort ? entries.sort(this.sortFunc) : entries; } - // a section will have a header and a list of docs. Ok cool. - return sections.map((section, i) => this.isStackingView ? this.sectionStacking(section[0], section[1]) : this.sectionMasonry(section[0], section[1], i === 0)); + return sections.map((section, i) => (this.isStackingView ? this.sectionStacking(section[0], section[1]) : this.sectionMasonry(section[0], section[1], i === 0))); } @computed get buttonMenu() { @@ -634,92 +659,90 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection const width: number = NumCast(menuDoc._width, 30); const height: number = NumCast(menuDoc._height, 30); console.log(menuDoc.title, width, height); - return (<div className="buttonMenu-docBtn" - style={{ width: width, height: height }}> - <DocumentView - Document={menuDoc} - DataDoc={menuDoc} - isContentActive={this.props.isContentActive} - isDocumentActive={returnTrue} - addDocument={this.props.addDocument} - moveDocument={this.props.moveDocument} - addDocTab={this.props.addDocTab} - pinToPres={emptyFunction} - rootSelected={this.props.isSelected} - removeDocument={this.props.removeDocument} - ScreenToLocalTransform={Transform.Identity} - PanelWidth={() => 35} - PanelHeight={() => 35} - renderDepth={this.props.renderDepth} - focus={emptyFunction} - styleProvider={this.props.styleProvider} - docViewPath={returnEmptyDoclist} - whenChildContentsActiveChanged={emptyFunction} - bringToFront={emptyFunction} - docFilters={this.props.docFilters} - docRangeFilters={this.props.docRangeFilters} - searchFilterDocs={this.props.searchFilterDocs} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} - /> - </div> + return ( + <div className="buttonMenu-docBtn" style={{ width: width, height: height }}> + <DocumentView + Document={menuDoc} + DataDoc={menuDoc} + isContentActive={this.props.isContentActive} + isDocumentActive={returnTrue} + addDocument={this.props.addDocument} + moveDocument={this.props.moveDocument} + addDocTab={this.props.addDocTab} + pinToPres={emptyFunction} + rootSelected={this.props.isSelected} + removeDocument={this.props.removeDocument} + ScreenToLocalTransform={Transform.Identity} + PanelWidth={() => 35} + PanelHeight={() => 35} + renderDepth={this.props.renderDepth} + focus={emptyFunction} + styleProvider={this.props.styleProvider} + docViewPath={returnEmptyDoclist} + whenChildContentsActiveChanged={emptyFunction} + bringToFront={emptyFunction} + docFilters={this.props.docFilters} + docRangeFilters={this.props.docRangeFilters} + searchFilterDocs={this.props.searchFilterDocs} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + /> + </div> ); } } + @computed get nativeWidth() { + return this.props.NativeWidth?.() ?? Doc.NativeWidth(this.layoutDoc); + } + @computed get nativeHeight() { + return this.props.NativeHeight?.() ?? Doc.NativeHeight(this.layoutDoc); + } - @computed get nativeWidth() { return this.props.NativeWidth?.() ?? Doc.NativeWidth(this.layoutDoc); } - @computed get nativeHeight() { return this.props.NativeHeight?.() ?? Doc.NativeHeight(this.layoutDoc); } - - @computed get scaling() { return !this.nativeWidth ? 1 : this.props.PanelHeight() / this.nativeHeight; } + @computed get scaling() { + return !this.nativeWidth ? 1 : this.props.PanelHeight() / this.nativeHeight; + } - @computed get backgroundEvents() { return SnappingManager.GetIsDragging(); } + @computed get backgroundEvents() { + return SnappingManager.GetIsDragging(); + } observer: any; render() { TraceMobx(); const editableViewProps = { - GetValue: () => "", + GetValue: () => '', SetValue: this.addGroup, - // I don't recall ever seeing this add a group button - contents: "+ ADD A GROUP" + contents: '+ ADD A GROUP', }; const buttonMenu = this.rootDoc.buttonMenu; const noviceExplainer = this.rootDoc.explainer; return ( <> - {buttonMenu || noviceExplainer ? <div className="documentButtonMenu"> - {buttonMenu ? this.buttonMenu : null} - {Doc.noviceMode && noviceExplainer ? - <div className="documentExplanation"> - {noviceExplainer} - </div> - : null - } - </div> : null} - <div className="collectionStackingMasonry-cont" > - <div className={this.isStackingView ? "collectionStackingView" : "collectionMasonryView"} + {buttonMenu || noviceExplainer ? ( + <div className="documentButtonMenu"> + {buttonMenu ? this.buttonMenu : null} + {Doc.noviceMode && noviceExplainer ? <div className="documentExplanation">{StrCast(noviceExplainer)}</div> : null} + </div> + ) : null} + <div className="collectionStackingMasonry-cont"> + <div + className={this.isStackingView ? 'collectionStackingView' : 'collectionMasonryView'} ref={this.createRef} style={{ - overflowY: this.props.isContentActive() ? "auto" : "hidden", + overflowY: this.props.isContentActive() ? 'auto' : 'hidden', background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor), - pointerEvents: this.backgroundEvents ? "all" : undefined + pointerEvents: this.backgroundEvents ? 'all' : undefined, }} - onScroll={action(e => this._scroll = e.currentTarget.scrollTop)} - onPointerOver={this.onPointerOver} - onPointerDown={this.onPointerDown} + onScroll={action(e => (this._scroll = e.currentTarget.scrollTop))} onDrop={this.onExternalDrop.bind(this)} onContextMenu={this.onContextMenu} - // Todo: what is wheel? Are we talking about a mouse wheel? - onWheel={e => this.props.isContentActive(true) && e.stopPropagation()} > - {/* so it appears that we are actually rendering the sections. Maybe this is what we're looking for? */} + onWheel={e => this.props.isContentActive(true) && e.stopPropagation()}> {this.renderedSections} - {/* I think that showAddGroup must be passed in as false, which is why we can't find what Mehek showed - Or it's because we aren't passing a pivot field */} - {!this.showAddAGroup ? (null) : - <div key={`${this.props.Document[Id]}-addGroup`} className="collectionStackingView-addGroupButton" - style={{ width: !this.isStackingView ? "100%" : this.columnWidth / this.numGroupColumns - 10, marginTop: 10 }}> + {!this.showAddAGroup ? null : ( + <div key={`${this.props.Document[Id]}-addGroup`} className="collectionStackingView-addGroupButton" style={{ width: !this.isStackingView ? '100%' : this.columnWidth / this.numGroupColumns - 10, marginTop: 10 }}> <EditableView {...editableViewProps} /> - </div>} + </div> + )} {/* {this.chromeHidden || !this.props.isSelected() ? (null) : <Switch onChange={this.onToggle} @@ -731,7 +754,6 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection </div> </div> </> - ); } } |
