diff options
| author | bobzel <zzzman@gmail.com> | 2024-05-19 01:01:02 -0400 |
|---|---|---|
| committer | bobzel <zzzman@gmail.com> | 2024-05-19 01:01:02 -0400 |
| commit | 6e72f969029c22fe797397a6437836a0482260b6 (patch) | |
| tree | e8ccde75702e557b2226c9069263e1bc3bd21a4b /src/client/views/collections/CollectionNoteTakingView.tsx | |
| parent | 5ff0bef5d3c4825aa7210a26c98aae3b24f4a835 (diff) | |
| parent | 13dc6de0e0099f699ad0d2bb54401e6a0aa25018 (diff) | |
Merge branch 'restoringEslint' into alyssa-starter
Diffstat (limited to 'src/client/views/collections/CollectionNoteTakingView.tsx')
| -rw-r--r-- | src/client/views/collections/CollectionNoteTakingView.tsx | 212 |
1 files changed, 145 insertions, 67 deletions
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index 6318620e0..16c474996 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -1,7 +1,8 @@ -import { action, computed, IReactionDisposer, makeObservable, observable, observe, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, Field, Opt } from '../../../fields/Doc'; +import { ClientUtils, DivHeight, lightOrDark, returnZero, smoothScroll } from '../../../ClientUtils'; +import { Doc, Field, FieldType, Opt } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { Copy, Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; @@ -9,24 +10,28 @@ 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 { DivHeight, emptyFunction, returnFalse, returnZero, smoothScroll, Utils } from '../../../Utils'; -import { Docs, DocUtils } from '../../documents/Documents'; -import { DragManager, dropActionType } from '../../util/DragManager'; +import { emptyFunction } from '../../../Utils'; +import { Docs } from '../../documents/Documents'; +import { DocUtils } from '../../documents/DocUtils'; +import { DragManager } from '../../util/DragManager'; +import { dropActionType } from '../../util/DropActionTypes'; import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; -import { undoBatch } from '../../util/UndoManager'; +import { undoable, undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; -import { LightboxView } from '../LightboxView'; +import { FieldsDropdown } from '../FieldsDropdown'; +import { Colors } from '../global/globalEnums'; +import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView'; import { DocumentView } from '../nodes/DocumentView'; -import { FocusViewOptions, FieldViewProps } from '../nodes/FieldView'; -import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; -import { StyleProp } from '../StyleProvider'; +import { FieldViewProps } from '../nodes/FieldView'; +import { FocusViewOptions } from '../nodes/FocusViewOptions'; +import { StyleProp } from '../StyleProp'; import './CollectionNoteTakingView.scss'; import { CollectionNoteTakingViewColumn } from './CollectionNoteTakingViewColumn'; import { CollectionNoteTakingViewDivider } from './CollectionNoteTakingViewDivider'; import { CollectionSubView } from './CollectionSubView'; -import { JsxElement } from 'typescript'; + const _global = (window /* browser */ || global) /* node */ as any; /** @@ -41,7 +46,9 @@ export class CollectionNoteTakingView extends CollectionSubView() { _disposers: { [key: string]: IReactionDisposer } = {}; _masonryGridRef: HTMLDivElement | null = null; _draggerRef = React.createRef<HTMLDivElement>(); - notetakingCategoryField = 'NotetakingCategory'; + @computed get notetakingCategoryField() { + return StrCast(this.dataDoc.notetaking_column, StrCast(this.layoutDoc.pivotField, 'notetaking_column')); + } public DividerWidth = 16; @observable docsDraggedRowCol: number[] = []; @observable _scroll = 0; @@ -53,7 +60,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { } @computed get chromeHidden() { - return BoolCast(this.layoutDoc.chromeHidden) || this._props.onBrowseClickScript?.() ? true : false; + return BoolCast(this.layoutDoc.chromeHidden) || SnappingManager.ExploreMode; } // columnHeaders returns the list of SchemaHeaderFields currently being used by the layout doc to render the columns @computed get colHeaderData() { @@ -62,7 +69,6 @@ export class CollectionNoteTakingView extends CollectionSubView() { if (needsUnsetCategory || colHeaderData === undefined || colHeaderData.length === 0) { setTimeout(() => { const columnHeaders = Array.from(Cast(this.dataDoc[this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null) ?? []); - const needsUnsetCategory = this.childDocs.some(d => !d[this.notetakingCategoryField] && !columnHeaders?.find(sh => sh.heading === 'unset')); if (needsUnsetCategory || columnHeaders.length === 0) { columnHeaders.push(new SchemaHeaderField('unset', undefined, undefined, 1)); this.resizeColumns(columnHeaders); @@ -106,12 +112,12 @@ export class CollectionNoteTakingView extends CollectionSubView() { // to render the docs you see within an individual column. children = (docs: Doc[]) => { TraceMobx(); - return docs.map((d, i) => { + return docs.map(d => { const height = () => this.getDocHeight(d); const width = () => this.getDocWidth(d); const style = { width: width(), marginTop: this.gridGap, height: height() }; return ( - <div className={`collectionNoteTakingView-columnDoc`} key={d[Id]} style={style}> + <div className="collectionNoteTakingView-columnDoc" key={d[Id]} style={style}> {this.getDisplayDoc(d, width)} </div> ); @@ -130,7 +136,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { const sections = new Map<SchemaHeaderField, Doc[]>(columnHeaders.map(sh => [sh, []] as [SchemaHeaderField, []])); const rowCol = this.docsDraggedRowCol; // this will sort the docs into the correct columns (minus the ones you're currently dragging) - docs.map(d => { + docs.forEach(d => { const sectionValue = (d[this.notetakingCategoryField] as object) ?? `unset`; // look for if header exists already const existingHeader = columnHeaders.find(sh => sh.heading === sectionValue.toString()); @@ -148,42 +154,51 @@ export class CollectionNoteTakingView extends CollectionSubView() { removeDocDragHighlight = () => { setTimeout( - action(() => (this.docsDraggedRowCol.length = 0)), + action(() => { + this.docsDraggedRowCol.length = 0; + }), 100 ); }; + @computed get allFieldValues() { + return new Set(this.childDocs.map(doc => StrCast(doc[this.notetakingCategoryField]))); + } + componentDidMount() { super.componentDidMount?.(); document.addEventListener('pointerup', this.removeDocDragHighlight, true); - this._disposers.layout_autoHeight = reaction( - () => this.layoutDoc._layout_autoHeight, - layout_autoHeight => layout_autoHeight && this._props.setHeight?.(this.headerMargin + Math.max(...this._refList.map(DivHeight))) + + this._disposers.autoColumns = reaction( + () => (this.layoutDoc._notetaking_columns_autoCreate ? Array.from(this.allFieldValues) : undefined), + columns => undoable(() => columns?.filter(col => !this.colHeaderData.some(h => h.heading === col)).forEach(col => this.addColumn(col)), 'adding columns')(), + { fireImmediately: true } ); this._disposers.refList = reaction( - () => ({ refList: this._refList.slice(), autoHeight: this.layoutDoc._layout_autoHeight && !LightboxView.Contains(this.DocumentView?.()) }), + () => ({ refList: this._refList.slice(), autoHeight: this.layoutDoc._layout_autoHeight && !DocumentView.LightboxContains(this.DocumentView?.()) }), ({ refList, autoHeight }) => { - if (autoHeight) refList.forEach(r => this.observer.observe(r)); - else this.observer.disconnect(); + if (autoHeight) { + refList.forEach(r => this.observer.observe(r)); + this._props.setHeight?.(this.headerMargin + Math.max(...this._refList.map(DivHeight))); + } else this.observer.disconnect(); }, { fireImmediately: true } ); } componentWillUnmount() { + this.observer.disconnect(); document.removeEventListener('pointerup', this.removeDocDragHighlight, true); super.componentWillUnmount(); Object.keys(this._disposers).forEach(key => this._disposers[key]()); } - moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[], annotationKey?: string) => boolean, annotationKey?: string): boolean => { - return this._props.removeDocument?.(doc) && addDocument?.(doc) ? true : false; - }; + moveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[], annotationKey?: string) => boolean) => !!(this._props.removeDocument?.(doc) && addDocument?.(doc)); createRef = (ele: HTMLDivElement | null) => { this._masonryGridRef = ele; - this.createDashEventsTarget(ele!); //so the whole grid is the drop target? + this.createDashEventsTarget(ele!); }; @computed get onChildClickHandler() { @@ -203,14 +218,15 @@ export class CollectionNoteTakingView extends CollectionSubView() { Doc.BrushDoc(doc); 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 { top } = found.getBoundingClientRect(); const localTop = this.ScreenToLocalBoxXf().transformPoint(0, top); if (Math.floor(localTop[1]) !== 0 && Math.ceil(this._props.PanelHeight()) < (this._mainCont?.scrollHeight || 0)) { - let focusSpeed = options.zoomTime ?? 500; + const focusSpeed = options.zoomTime ?? 500; smoothScroll(focusSpeed, this._mainCont!, localTop[1] + this._mainCont!.scrollTop, options.easeFunc); return focusSpeed; } } + return undefined; }; styleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string) => { @@ -225,6 +241,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { return this._props.childOpacity(); } break; + default: } return this._props.styleProvider?.(doc, props, property); }; @@ -240,7 +257,9 @@ export class CollectionNoteTakingView extends CollectionSubView() { const noteTakingDocTransform = () => this.getDocTransform(doc, dref); return ( <DocumentView - ref={r => (dref = r || undefined)} + ref={r => { + dref = r || undefined; + }} Document={doc} TemplateDataDocument={dataDoc ?? (!Doc.AreProtosEqual(doc[DocData], doc) ? doc[DocData] : undefined)} pointerEvents={this.blockPointerEventsWhenDragging} @@ -249,11 +268,11 @@ export class CollectionNoteTakingView extends CollectionSubView() { PanelHeight={height} styleProvider={this.styleProvider} containerViewPath={this.childContainerViewPath} - layout_fitWidth={this._props.childLayoutFitWidth} + fitWidth={this._props.childLayoutFitWidth} isContentActive={emptyFunction} onKey={this.onKeyDown} - //TODO: change this from a prop to a parameter passed into a function - dontHideOnDrag={true} + // TODO: change this from a prop to a parameter passed into a function + dontHideOnDrag isDocumentActive={this.isContentActive} LayoutTemplate={this._props.childLayoutTemplate} LayoutTemplateString={this._props.childLayoutString} @@ -262,10 +281,9 @@ export class CollectionNoteTakingView extends CollectionSubView() { dontCenter={this._props.childIgnoreNativeSize ? 'xy' : undefined} dontRegisterView={dataDoc ? true : BoolCast(this.layoutDoc.childDontRegisterViews, this._props.dontRegisterView)} rootSelected={this.rootSelected} - layout_showTitle={this._props.childlayout_showTitle} + showTitle={this._props.childlayout_showTitle} dragAction={StrCast(this.layoutDoc.childDragAction) as dropActionType} onClickScript={this.onChildClickHandler} - onBrowseClickScript={this._props.onBrowseClickScript} onDoubleClickScript={this.onChildDoubleClickHandler} ScreenToLocalTransform={noteTakingDocTransform} focus={this.focusDocument} @@ -287,8 +305,8 @@ export class CollectionNoteTakingView extends CollectionSubView() { // getDocTransform is used to get the coordinates of a document when we go from a view like freeform to columns getDocTransform(doc: Doc, dref?: DocumentView) { - const y = this._scroll; // required for document decorations to update when the text box container is scrolled - const { translateX, translateY } = Utils.GetScreenTransform(dref?.ContentDiv || undefined); + this._scroll; // required for document decorations to update when the text box container is scrolled + const { translateX, translateY } = ClientUtils.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.ScreenToLocalBoxXf().Scale); } @@ -296,9 +314,9 @@ export class CollectionNoteTakingView extends CollectionSubView() { // how to get the width of a document. Currently returns the width of the column (minus margins) // if a note doc. Otherwise, returns the normal width (for graphs, images, etc...) getDocWidth(d: Doc) { - const heading = !d[this.notetakingCategoryField] ? 'unset' : Field.toString(d[this.notetakingCategoryField] as Field); + const heading = !d[this.notetakingCategoryField] ? 'unset' : Field.toString(d[this.notetakingCategoryField] as FieldType); const existingHeader = this.colHeaderData.find(sh => sh.heading === heading); - const existingWidth = existingHeader?.width ? existingHeader.width : 0; + const existingWidth = this.layoutDoc._notetaking_columns_autoSize ? 1 / (this.colHeaderData.length ?? 1) : existingHeader?.width ? existingHeader.width : 0; const maxWidth = existingWidth > 0 ? existingWidth * this.availableWidth : this.maxColWidth; const width = d.layout_fitWidth ? maxWidth : NumCast(d._width); return Math.min(maxWidth - CollectionNoteTakingViewColumn.ColumnMargin, width < maxWidth ? width : maxWidth); @@ -332,7 +350,6 @@ export class CollectionNoteTakingView extends CollectionSubView() { // Adding example: column widths are [0.6, 0.4] --> user adds column at end --> column widths are [0.4, 0.267, 0.33] @action resizeColumns = (headers: SchemaHeaderField[]) => { - const n = headers.length; const curWidths = headers.reduce((sum, hdr) => sum + Math.abs(hdr.width), 0); const scaleFactor = 1 / curWidths; this.dataDoc[this.fieldKey + '_columnHeaders'] = new List<SchemaHeaderField>( @@ -370,7 +387,11 @@ export class CollectionNoteTakingView extends CollectionSubView() { // we alter the pivot fields of the docs in case they are moved to a new column. const colIndex = this.getColumnFromXCoord(xCoord); const colHeader = colIndex === undefined ? 'unset' : StrCast(this.colHeaderData[colIndex].heading); - DragManager.docsBeingDragged.forEach(d => (d[this.notetakingCategoryField] = colHeader)); + DragManager.docsBeingDragged + .map(doc => doc[DocData]) + .forEach(d => { + d[this.notetakingCategoryField] = colHeader; + }); // used to notify sections to re-render this.docsDraggedRowCol.length = 0; const columnFromCoord = this.getColumnFromXCoord(xCoord); @@ -381,7 +402,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { // getColumnFromXCoord returns the column index for a given x-coordinate (currently always the client's mouse coordinate). // This function is used to know which document a column SHOULD be in while it is being dragged. getColumnFromXCoord = (xCoord: number): number | undefined => { - let colIndex: number | undefined = undefined; + let colIndex: number | undefined; const numColumns = this.colHeaderData.length; const coords = []; let colStartXCoord = 0; @@ -404,10 +425,10 @@ export class CollectionNoteTakingView extends CollectionSubView() { const docsMatchingHeader: Doc[] = []; const colIndex = this.getColumnFromXCoord(xCoord); const colHeader = colIndex === undefined ? 'unset' : StrCast(this.colHeaderData[colIndex].heading); - this.childDocs?.map(d => { + this.childDocs?.forEach(d => { if (d instanceof Promise) return; const sectionValue = (d[this.notetakingCategoryField] as object) ?? 'unset'; - if (sectionValue.toString() == colHeader) { + if (sectionValue.toString() === colHeader) { docsMatchingHeader.push(d); } }); @@ -420,9 +441,10 @@ export class CollectionNoteTakingView extends CollectionSubView() { e.stopPropagation?.(); const newDoc = Doc.MakeCopy(fieldProps.Document, true); newDoc[DocData].text = undefined; - FormattedTextBox.SetSelectOnLoad(newDoc); + Doc.SetSelectOnLoad(newDoc); return this.addDocument?.(newDoc); } + return undefined; }; // onInternalDrop is used when dragging and dropping a document within the view, such as dragging @@ -451,7 +473,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { } return true; } - } else if (de.complete.linkDragData?.dragDocument.embedContainer === this.Document && de.complete.linkDragData?.linkDragView?.CollectionFreeFormDocumentView) { + } else if (de.complete.linkDragData?.dragDocument.embedContainer === this.Document && CollectionFreeFormDocumentView.from(de.complete.linkDragData?.linkDragView)) { const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _layout_fitWidth: true, title: 'dropped annotation' }); if (!this._props.addDocument?.(source)) e.preventDefault(); de.complete.linkDocument = DocUtils.MakeLink(source, de.complete.linkDragData.linkSourceGetAnchor(), { link_relationship: 'doc annotation' }); // TODODO this is where in text links get passed @@ -500,11 +522,12 @@ export class CollectionNoteTakingView extends CollectionSubView() { editableViewProps = () => ({ GetValue: () => '', - SetValue: this.addGroup, - contents: '+ New Column', + SetValue: this.addColumn, + contents: '+ Column', }); refList = () => this._refList; + backgroundColor = () => this.DocumentView?.()?.backgroundColor(); // sectionNoteTaking returns a CollectionNoteTakingViewColumn (which is an individual column) sectionNoteTaking = (heading: SchemaHeaderField | undefined, docList: Doc[]) => ( @@ -512,7 +535,9 @@ export class CollectionNoteTakingView extends CollectionSubView() { key={heading?.heading ?? 'unset'} PanelWidth={this._props.PanelWidth} refList={this._refList} + backgroundColor={this.backgroundColor} select={this._props.select} + isContentActive={this.isContentActive} addDocument={this.addDocument} chromeHidden={this.chromeHidden} colHeaderData={this.colHeaderData} @@ -538,18 +563,27 @@ export class CollectionNoteTakingView extends CollectionSubView() { /> ); + @undoBatch + remColumn = (value: SchemaHeaderField) => { + const colHdrData = Array.from(Cast(this._props.Document[this._props.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null)); + if (value) { + const index = colHdrData.indexOf(value); + index !== -1 && colHdrData.splice(index, 1); + this.resizeColumns(colHdrData); + } + }; + // addGroup is called when adding a new columnHeader, adding a SchemaHeaderField to our list of // columnHeaders and resizing the existing columns to make room for our new one. @undoBatch - addGroup = (value: string) => { - if (this.colHeaderData) { - for (const header of this.colHeaderData) { - if (header.heading === value) { - alert('You cannot use an existing column name. Please try a new column name'); - return value; - } + addColumn = (value: string) => { + this.colHeaderData.forEach(header => { + if (header.heading === value) { + alert('You cannot use an existing column name. Please try a new column name'); + return value; } - } + return undefined; + }); const columnHeaders = Array.from(Cast(this.dataDoc[this.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null)); const newColWidth = 1 / (this.numGroupColumns + 1); columnHeaders.push(new SchemaHeaderField(value, undefined, undefined, newColWidth)); @@ -557,13 +591,43 @@ export class CollectionNoteTakingView extends CollectionSubView() { return true; }; + removeEmptyColumns = undoable(() => { + this.colHeaderData.filter(h => !this.allFieldValues.has(h.heading)).forEach(this.remColumn); + }, 'remove empty Columns'); + 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._layout_autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => (this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight), icon: 'plus' }); - subItems.push({ description: 'Clear All', event: () => (this.dataDoc.data = new List([])), icon: 'times' }); + subItems.push({ + description: `${this.layoutDoc._notetaking_columns_autoCreate ? 'Manually' : 'Automatically'} Create columns`, + event: () => { + this.layoutDoc._notetaking_columns_autoCreate = !this.layoutDoc._notetaking_columns_autoCreate; + }, + icon: 'computer', + }); + subItems.push({ description: 'Remove Empty Columns', event: this.removeEmptyColumns, icon: 'computer' }); + subItems.push({ + description: `${this.layoutDoc._notetaking_columns_autoSize ? 'Variable Size' : 'Autosize'} Columns`, + event: () => { + this.layoutDoc._notetaking_columns_autoSize = !this.layoutDoc._notetaking_columns_autoSize; + }, + icon: 'plus', + }); + subItems.push({ + description: `${this.layoutDoc._layout_autoHeight ? 'Variable Height' : 'Auto Height'}`, + event: () => { + this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_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' }); } }; @@ -588,6 +652,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { const sections = Array.from(this.Sections.entries()); return sections.reduce((list, sec, i) => { list.push(this.sectionNoteTaking(sec[0], sec[1])); + // eslint-disable-next-line react/no-array-index-key i !== sections.length - 1 && list.push(<CollectionNoteTakingViewDivider key={`divider${i}`} isContentActive={this.isContentActive} index={i} setColumnStartXCoords={this.setColumnStartXCoords} xMargin={this.xMargin} />); return list; }, [] as JSX.Element[]); @@ -614,22 +679,35 @@ export class CollectionNoteTakingView extends CollectionSubView() { TraceMobx(); return ( <div - className="collectionNoteTakingView" + className={`collectionNoteTakingView ${lightOrDark(this.backgroundColor()) === Colors.WHITE ? 'collectionNoteTakingViewLight' : ''}`} ref={this.createRef} - key="notes" style={{ - overflowY: this._props.isContentActive() ? 'auto' : 'hidden', - background: this._props.styleProvider?.(this.Document, this._props, StyleProp.BackgroundColor), + overflowY: this.isContentActive() ? 'auto' : 'hidden', + background: this.backgroundColor(), pointerEvents: this.backgroundEvents, }} - onScroll={action(e => (this._scroll = e.currentTarget.scrollTop))} - onPointerLeave={action(e => (this.docsDraggedRowCol.length = 0))} + onScroll={action(e => { + this._scroll = e.currentTarget.scrollTop; + })} + onPointerLeave={action(() => { + this.docsDraggedRowCol.length = 0; + })} onPointerMove={e => e.buttons && this.onPointerMove(false, e.clientX, e.clientY)} onDragOver={e => this.onPointerMove(true, e.clientX, e.clientY)} onDrop={this.onExternalDrop.bind(this)} onContextMenu={this.onContextMenu} onWheel={e => this._props.isContentActive() && e.stopPropagation()}> - <>{this.renderedSections}</> + {this.renderedSections} + <div className="collectionNotetaking-pivotField" style={{ right: 0, top: 0, position: 'absolute' }}> + <FieldsDropdown + Document={this.Document} + selectFunc={undoable(fieldKey => { + this.layoutDoc._pivotField = fieldKey; + this.removeEmptyColumns(); + }, 'change pivot field')} + placeholder={StrCast(this.layoutDoc._pivotField)} + /> + </div> </div> ); } |
