diff options
Diffstat (limited to 'src/client/views/collections/collectionSchema')
5 files changed, 131 insertions, 88 deletions
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index 3a0c2c85c..52ebb7763 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -104,7 +104,7 @@ .schema-header-row { cursor: grab; - justify-content: flex-end; + //justify-content: flex-end; .row-menu { display: flex; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index bcc2ca129..babe5c810 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -8,17 +8,16 @@ import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; -import { emptyFunction, returnDefault, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils'; +import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils'; import { Docs, DocumentOptions, DocUtils, FInfo } from '../../../documents/Documents'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager } from '../../../util/DragManager'; import { SelectionManager } from '../../../util/SelectionManager'; -import { undoBatch } from '../../../util/UndoManager'; +import { undoable, undoBatch } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; import { EditableView } from '../../EditableView'; import { Colors } from '../../global/globalEnums'; import { DocFocusOptions, DocumentView } from '../../nodes/DocumentView'; -import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { KeyValueBox } from '../../nodes/KeyValueBox'; import { DefaultStyleProvider } from '../../StyleProvider'; import { CollectionSubView } from '../CollectionSubView'; @@ -33,6 +32,7 @@ export enum ColumnType { Date, Image, RTF, + Enumeration, Any, } @@ -43,9 +43,10 @@ export const FInfotoColType: { [key: string]: ColumnType } = { date: ColumnType.Date, image: ColumnType.Image, rtf: ColumnType.RTF, + enumeration: ColumnType.Enumeration, }; -const defaultColumnKeys: string[] = ['title', 'type', 'author', 'creationDate', 'text']; +const defaultColumnKeys: string[] = ['title', 'type', 'author', 'author_date', 'text']; @observer export class CollectionSchemaView extends CollectionSubView() { @@ -55,6 +56,7 @@ export class CollectionSchemaView extends CollectionSubView() { private _makeNewColumn: boolean = false; private _documentOptions: DocumentOptions = new DocumentOptions(); private _tableContentRef: HTMLDivElement | null = null; + private _menuTarget = React.createRef<HTMLDivElement>(); static _rowHeight: number = 50; static _rowSingleLineHeight: number = 32; @@ -78,6 +80,11 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _filterSearchValue: string = ''; @observable _selectedCell: [Doc, number] | undefined; + // target HTMLelement portal for showing a popup menu to edit cell values. + public get MenuTarget() { + return this._menuTarget.current; + } + @computed get _selectedDocs() { return SelectionManager.Docs().filter(doc => Doc.AreProtosEqual(DocCast(doc.embedContainer), this.rootDoc)); } @@ -224,7 +231,7 @@ export class CollectionSchemaView extends CollectionSubView() { @undoBatch @action - setSort = (field: string | undefined, desc: boolean = false) => { + setColumnSort = (field: string | undefined, desc: boolean = false) => { this.layoutDoc.sortField = field; this.layoutDoc.sortDesc = desc; }; @@ -337,9 +344,7 @@ export class CollectionSchemaView extends CollectionSubView() { dragColumn = (e: PointerEvent, index: number) => { const dragData = new DragManager.ColumnDragData(index); const dragEles = [this._colEles[index]]; - this.childDocs.forEach(doc => { - dragEles.push(this._rowEles.get(doc).children[1].children[index]); - }); + this.childDocs.forEach(doc => dragEles.push(this._rowEles.get(doc).children[1].children[index])); DragManager.StartColumnDrag(dragEles, dragData, e.x, e.y); document.removeEventListener('pointermove', this.highlightDropColumn); @@ -353,24 +358,28 @@ export class CollectionSchemaView extends CollectionSubView() { return true; }; - @action - highlightDropColumn = (e: PointerEvent) => { - e.stopPropagation(); - const mouseX = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0]; + findDropIndex = (mouseX: number) => { let index: number | undefined; this.displayColumnWidths.reduce((total, curr, i) => { if (total <= mouseX && total + curr >= mouseX) { - if (mouseX <= total + curr / 2) index = i; + if (mouseX <= total + curr) index = i; else index = i + 1; } return total + curr; }, CollectionSchemaView._rowMenuWidth); + return index; + }; + @action + highlightDropColumn = (e: PointerEvent) => { + e.stopPropagation(); + const mouseX = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0]; + const index = this.findDropIndex(mouseX); this._colEles.forEach((colRef, i) => { let leftStyle = ''; let rightStyle = ''; - if (i + 1 === index) rightStyle = `solid 2px ${Colors.MEDIUM_BLUE}`; - if (i === index && i === 0) leftStyle = `solid 2px ${Colors.MEDIUM_BLUE}`; + if (i + 1 === index) rightStyle = `solid 12px ${Colors.MEDIUM_BLUE}`; + if (i === index && i === 0) leftStyle = `solid 12px ${Colors.MEDIUM_BLUE}`; colRef.style.borderLeft = leftStyle; colRef.style.borderRight = rightStyle; this.childDocs.forEach(doc => { @@ -425,17 +434,9 @@ export class CollectionSchemaView extends CollectionSubView() { @action onInternalDrop = (e: Event, de: DragManager.DropEvent) => { if (de.complete.columnDragData) { - e.stopPropagation(); const mouseX = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y)[0]; - let index = de.complete.columnDragData.colIndex; - this.displayColumnWidths.reduce((total, curr, i) => { - if (total <= mouseX && total + curr >= mouseX) { - if (mouseX <= total + curr / 2) index = i; - else index = i + 1; - } - return total + curr; - }, CollectionSchemaView._rowMenuWidth); - this.moveColumn(de.complete.columnDragData.colIndex, index); + const index = this.findDropIndex(mouseX); + this.moveColumn(de.complete.columnDragData.colIndex, index ?? de.complete.columnDragData.colIndex); this._colEles.forEach((colRef, i) => { colRef.style.borderLeft = ''; @@ -446,6 +447,7 @@ export class CollectionSchemaView extends CollectionSubView() { }); }); + e.stopPropagation(); return true; } const draggedDocs = de.complete.docDragData?.draggedDocuments; @@ -460,7 +462,6 @@ export class CollectionSchemaView extends CollectionSubView() { if (draggedView) DocumentManager.Instance.RemoveView(draggedView); DocumentManager.Instance.AddViewRenderedCb(doc, dv => dv.select(true)); }); - e.stopPropagation(); return true; } return false; @@ -484,24 +485,11 @@ export class CollectionSchemaView extends CollectionSubView() { return false; }; - @action - addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => { - if (!value && !forceEmptyNote) return false; - const newDoc = Docs.Create.TextDocument(value, { title: value, _layout_autoHeight: true }); - FormattedTextBox.SelectOnLoad = newDoc[Id]; - FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? '' : ' '; - return this.addRow(newDoc) || false; - }; - menuCallback = (x: number, y: number) => { ContextMenu.Instance.clearItems(); - DocUtils.addDocumentCreatorMenuItems(doc => this.addRow(doc), this.addRow, x, y, true); + DocUtils.addDocumentCreatorMenuItems(this.addRow, this.addRow, x, y, true); - ContextMenu.Instance.setDefaultItem('::', (name: string): void => { - Doc.GetProto(this.props.Document)[name] = ''; - this.addRow(Docs.Create.TextDocument('', { title: name, _layout_autoHeight: true })); - }); ContextMenu.Instance.displayMenu(x, y, undefined, true); }; @@ -621,7 +609,7 @@ export class CollectionSchemaView extends CollectionSubView() { this._menuKeys = this.documentKeys.filter(value => value.toLowerCase().includes(this._menuValue.toLowerCase())); }; - getFieldFilters = (field: string) => StrListCast(this.Document._docFilters).filter(filter => filter.split(':')[0] == field); + getFieldFilters = (field: string) => StrListCast(this.Document._childFilters).filter(filter => filter.split(':')[0] == field); removeFieldFilters = (field: string) => { this.getFieldFilters(field).forEach(filter => Doc.setDocFilter(this.Document, field, filter.split(':')[1], 'remove')); @@ -697,6 +685,12 @@ export class CollectionSchemaView extends CollectionSubView() { ); } + onPassiveWheel = (e: WheelEvent) => { + // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this) + if (!this._oldWheel.scrollTop && e.deltaY <= 0) e.preventDefault(); + e.stopPropagation(); + }; + _oldWheel: any; @computed get keysDropdown() { return ( <div className="schema-key-search"> @@ -710,16 +704,11 @@ export class CollectionSchemaView extends CollectionSubView() { </div> <div className="schema-key-list" - ref={r => - r?.addEventListener( - 'wheel', // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this) - (e: WheelEvent) => { - if (!r.scrollTop && e.deltaY <= 0) e.preventDefault(); - e.stopPropagation(); - }, - { passive: false } - ) - }> + ref={r => { + this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel); + this._oldWheel = r; + r?.addEventListener('wheel', this.onPassiveWheel, { passive: false }); + }}> {this._menuKeys.map(key => ( <div className="schema-search-result" @@ -773,7 +762,7 @@ export class CollectionSchemaView extends CollectionSubView() { } }); - const filters = StrListCast(this.Document._docFilters); + const filters = StrListCast(this.Document._childFilters); return keyOptions.map(key => { let bool = false; if (filters !== undefined) { @@ -821,7 +810,6 @@ export class CollectionSchemaView extends CollectionSubView() { } @computed get sortedDocs() { - trace(); const field = StrCast(this.layoutDoc.sortField); const desc = BoolCast(this.layoutDoc.sortDesc); const docs = !field @@ -845,6 +833,7 @@ export class CollectionSchemaView extends CollectionSubView() { render() { return ( <div className="collectionSchemaView" ref={(ele: HTMLDivElement | null) => this.createDashEventsTarget(ele)} onDrop={this.onExternalDrop.bind(this)}> + <div ref={this._menuTarget} style={{ background: 'red', top: 0, left: 0, position: 'absolute', zIndex: 10000 }}></div> <div className="schema-table" onWheel={e => this.props.isContentActive() && e.stopPropagation()} @@ -866,20 +855,28 @@ export class CollectionSchemaView extends CollectionSubView() { columnWidths={this.displayColumnWidths} sortField={this.sortField} sortDesc={this.sortDesc} - setSort={this.setSort} + setSort={this.setColumnSort} rowHeight={this.rowHeightFunc} removeColumn={this.removeColumn} resizeColumn={this.startResize} openContextMenu={this.openContextMenu} dragColumn={this.dragColumn} setColRef={this.setColRef} + isContentActive={this.props.isContentActive} /> ))} </div> {this._columnMenuIndex !== undefined && this.renderColumnMenu} {this._filterColumnIndex !== undefined && this.renderFilterMenu} <CollectionSchemaViewDocs schema={this} childDocs={this.sortedDocsFunc} rowHeight={this.rowHeightFunc} setRef={(ref: HTMLDivElement | null) => (this._tableContentRef = ref)} /> - <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} height={CollectionSchemaView._newNodeInputHeight} /> + <EditableView + GetValue={returnEmptyString} + SetValue={undoable(value => (value ? this.addRow(Docs.Create.TextDocument(value, { title: value, _layout_autoHeight: true })) : false), 'add text doc')} + placeholder={"Type ':' for commands"} + contents={'+ New Node'} + menuCallback={this.menuCallback} + height={CollectionSchemaView._newNodeInputHeight} + /> </div> {this.previewWidth > 0 && <div className="schema-preview-divider" style={{ width: CollectionSchemaView._previewDividerWidth }} onPointerDown={this.onDividerDown}></div>} {this.previewWidth > 0 && ( @@ -900,8 +897,8 @@ export class CollectionSchemaView extends CollectionSubView() { isContentActive={returnTrue} isDocumentActive={returnFalse} ScreenToLocalTransform={this.screenToLocal} - docFilters={this.childDocFilters} - docRangeFilters={this.childDocRangeFilters} + childFilters={this.childDocFilters} + childFiltersByRanges={this.childDocRangeFilters} searchFilterDocs={this.searchFilterDocs} styleProvider={DefaultStyleProvider} docViewPath={returnEmptyDoclist} @@ -946,17 +943,18 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP LayoutTemplateString={SchemaRowBox.LayoutString(this.props.schema.props.fieldKey)} Document={doc} DataDoc={dataDoc} + yPadding={index} renderDepth={this.props.schema.props.renderDepth + 1} PanelWidth={this.tableWidthFunc} PanelHeight={this.props.rowHeight} styleProvider={DefaultStyleProvider} waitForDoubleClickToClick={returnNever} defaultDoubleClick={returnIgnore} - enableDragWhenActive={true} + dragAction="move" onClickScriptDisable="always" focus={this.props.schema.focusDocument} - docFilters={this.props.schema.childDocFilters} - docRangeFilters={this.props.schema.childDocRangeFilters} + childFilters={this.props.schema.childDocFilters} + childFiltersByRanges={this.props.schema.childDocRangeFilters} searchFilterDocs={this.props.schema.searchFilterDocs} rootSelected={this.props.schema.rootSelected} ScreenToLocalTransform={this.childScreenToLocal(index)} @@ -970,7 +968,6 @@ class CollectionSchemaViewDocs extends React.Component<CollectionSchemaViewDocsP hideLinkAnchors={true} layout_fitWidth={returnTrue} scriptContext={this} - canEmbedOnDrag={true} /> </div> ); diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index 7da3c042c..65e47f441 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -5,8 +5,6 @@ import { observer } from 'mobx-react'; import { emptyFunction, setupMoveUpEvents } from '../../../../Utils'; import { Colors } from '../../global/globalEnums'; import './CollectionSchemaView.scss'; -import { SnappingManager } from '../../../util/SnappingManager'; -import { DragManager } from '../../../util/DragManager'; export interface SchemaColumnHeaderProps { columnKeys: string[]; @@ -14,6 +12,7 @@ export interface SchemaColumnHeaderProps { columnIndex: number; sortField: string; sortDesc: boolean; + isContentActive: (outsideReaction?: boolean | undefined) => boolean | undefined; setSort: (field: string | undefined, desc?: boolean) => void; removeColumn: (index: number) => void; rowHeight: () => number; @@ -46,7 +45,7 @@ export class SchemaColumnHeader extends React.Component<SchemaColumnHeaderProps> @action onPointerDown = (e: React.PointerEvent) => { - setupMoveUpEvents(this, e, e => this.props.dragColumn(e, this.props.columnIndex), emptyFunction, emptyFunction, false); + this.props.isContentActive(true) && setupMoveUpEvents(this, e, e => this.props.dragColumn(e, this.props.columnIndex), emptyFunction, emptyFunction, false); }; render() { diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 45bfe4f77..e8e606030 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -7,7 +7,7 @@ import { Doc } from '../../../../fields/Doc'; import { BoolCast } from '../../../../fields/Types'; import { DragManager } from '../../../util/DragManager'; import { SnappingManager } from '../../../util/SnappingManager'; -import { undoBatch } from '../../../util/UndoManager'; +import { undoable } from '../../../util/UndoManager'; import { ViewBoxBaseComponent } from '../../DocComponent'; import { Colors } from '../../global/globalEnums'; import { OpenWhere } from '../../nodes/DocumentView'; @@ -15,6 +15,7 @@ import { FieldView, FieldViewProps } from '../../nodes/FieldView'; import { CollectionSchemaView } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; import { SchemaTableCell } from './SchemaTableCell'; +import { Transform } from '../../../util/Transform'; @observer export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps>() { @@ -52,13 +53,13 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps>() { }; onPointerEnter = (e: any) => { - if (!SnappingManager.GetIsDragging()) return; - document.removeEventListener('pointermove', this.onPointerMove); - document.addEventListener('pointermove', this.onPointerMove); + if (SnappingManager.GetIsDragging() && this.props.isContentActive()) { + document.removeEventListener('pointermove', this.onPointerMove); + document.addEventListener('pointermove', this.onPointerMove); + } }; onPointerMove = (e: any) => { - if (!SnappingManager.GetIsDragging()) return; const dragIsRow = DragManager.docsBeingDragged.some(doc => doc.embedContainer === this.schemaDoc); // this.schemaView?._selectedDocs.has(doc) ?? false; if (this._ref && dragIsRow) { @@ -111,18 +112,18 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps>() { }}> <div className="schema-row-button" - onPointerDown={undoBatch(e => { + onPointerDown={undoable(e => { e.stopPropagation(); this.props.removeDocument?.(this.rootDoc); - })}> + }, 'Delete Row')}> <FontAwesomeIcon icon="times" /> </div> <div className="schema-row-button" - onPointerDown={e => { + onPointerDown={undoable(e => { e.stopPropagation(); this.props.addDocTab(this.rootDoc, OpenWhere.addRight); - }}> + }, 'Open Doc on Right')}> <FontAwesomeIcon icon="external-link-alt" /> </div> </div> @@ -143,6 +144,13 @@ export class SchemaRowBox extends ViewBoxBaseComponent<FieldViewProps>() { selectedCell={this.selectedCell} setColumnValues={this.setColumnValues} oneLine={BoolCast(this.schemaDoc?._singleLine)} + menuTarget={this.schemaView.MenuTarget} + transform={() => { + const ind = index === this.schemaView.columnKeys.length - 1 ? this.schemaView.columnKeys.length - 3 : index; + const x = this.schemaView?.displayColumnWidths.reduce((p, c, i) => (i <= ind ? p + c : p), 0); + const y = (this.props.yPadding ?? 0) * this.props.PanelHeight(); + return new Transform(x + CollectionSchemaView._rowMenuWidth, y, 1); + }} /> ))} </div> diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 42bf32475..1c9c0de53 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -1,4 +1,5 @@ -import React = require('react'); +import * as React from 'react'; +import Select, { MenuPlacement } from 'react-select'; import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import { extname } from 'path'; @@ -6,14 +7,13 @@ import DatePicker from 'react-datepicker'; import { DateField } from '../../../../fields/DateField'; import { Doc, DocListCast, Field } from '../../../../fields/Doc'; import { RichTextField } from '../../../../fields/RichTextField'; -import { BoolCast, Cast, DateCast, FieldValue } from '../../../../fields/Types'; +import { BoolCast, Cast, DateCast, DocCast, FieldValue, StrCast } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero, Utils } from '../../../../Utils'; import { FInfo } from '../../../documents/Documents'; import { DocFocusOrOpen } from '../../../util/DocumentManager'; -import { dropActionType } from '../../../util/DragManager'; import { Transform } from '../../../util/Transform'; -import { undoBatch } from '../../../util/UndoManager'; +import { undoable, undoBatch } from '../../../util/UndoManager'; import { EditableView } from '../../EditableView'; import { Colors } from '../../global/globalEnums'; import { OpenWhere } from '../../nodes/DocumentView'; @@ -21,7 +21,7 @@ import { FieldView, FieldViewProps } from '../../nodes/FieldView'; import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { KeyValueBox } from '../../nodes/KeyValueBox'; import { DefaultStyleProvider } from '../../StyleProvider'; -import { ColumnType, FInfotoColType } from './CollectionSchemaView'; +import { CollectionSchemaView, ColumnType, FInfotoColType } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; export interface SchemaTableCellProps { @@ -41,6 +41,9 @@ export interface SchemaTableCellProps { oneLine?: boolean; // whether all input should fit on one line vs allowing textare multiline inputs allowCRs?: boolean; // allow carriage returns in text input (othewrise CR ends the edit) finishEdit?: () => void; // notify container that edit is over (eg. to hide view in DashFieldView) + options?: string[]; + menuTarget: HTMLDivElement | null; + transform: () => Transform; } @observer @@ -58,14 +61,14 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> { break; } protoCount++; - doc = doc.proto; + doc = DocCast(doc.proto); } const parenCount = Math.max(0, protoCount - 1); const color = protoCount === 0 || (fieldKey.startsWith('_') && Document[fieldKey] === undefined) ? 'black' : 'blue'; const textDecoration = color !== 'black' && parenCount ? 'underline' : ''; const fieldProps: FieldViewProps = { - docFilters: returnEmptyFilter, - docRangeFilters: returnEmptyFilter, + childFilters: returnEmptyFilter, + childFiltersByRanges: returnEmptyFilter, searchFilterDocs: returnEmptyDoclist, styleProvider: DefaultStyleProvider, docViewPath: returnEmptyDoclist, @@ -73,7 +76,7 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> { isSelected: returnFalse, setHeight: returnFalse, select: emptyFunction, - dropAction: 'embed', + dragAction: 'move', bringToFront: emptyFunction, renderDepth: 1, isContentActive: returnFalse, @@ -115,29 +118,29 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> { contents={<FieldView {...fieldProps} />} editing={this.selected ? undefined : false} GetValue={() => Field.toKeyValueString(this.props.Document, this.props.fieldKey)} - SetValue={undoBatch((value: string, shiftDown?: boolean, enterKey?: boolean) => { + SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { this.props.setColumnValues(this.props.fieldKey.replace(/^_/, ''), value); } const ret = KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), value); this.props.finishEdit?.(); return ret; - })} + }, 'edit schema cell')} /> </div> ); } get getCellType() { + const columnTypeStr = this.props.getFinfo(this.props.fieldKey)?.fieldType; const cellValue = this.props.Document[this.props.fieldKey]; if (cellValue instanceof ImageField) return ColumnType.Image; if (cellValue instanceof DateField) return ColumnType.Date; if (cellValue instanceof RichTextField) return ColumnType.RTF; if (typeof cellValue === 'number') return ColumnType.Any; - if (typeof cellValue === 'string') return ColumnType.Any; + if (typeof cellValue === 'string' && columnTypeStr !== 'enumeration') return ColumnType.Any; if (typeof cellValue === 'boolean') return ColumnType.Boolean; - const columnTypeStr = this.props.getFinfo(this.props.fieldKey)?.fieldType; if (columnTypeStr && columnTypeStr in FInfotoColType) { return FInfotoColType[columnTypeStr]; } @@ -152,6 +155,7 @@ export class SchemaTableCell extends React.Component<SchemaTableCellProps> { case ColumnType.Image: return <SchemaImageCell {...this.props} />; case ColumnType.Boolean: return <SchemaBoolCell {...this.props} />; case ColumnType.RTF: return <SchemaRTFCell {...this.props} />; + case ColumnType.Enumeration: return <SchemaEnumerationCell {...this.props} options={this.props.getFinfo(this.props.fieldKey)?.values?.map(val => val.toString())} />; case ColumnType.Date: // return <SchemaDateCell {...this.props} />; default: return this.defaultCellContent; } @@ -268,7 +272,7 @@ export class SchemaRTFCell extends React.Component<SchemaTableCellProps> { fieldProps.isContentActive = this.selectedFunc; return ( <div className="schemaRTFCell" style={{ display: 'flex', fontStyle: this.selected ? undefined : 'italic', width: '100%', height: '100%', position: 'relative', color, textDecoration, cursor, pointerEvents }}> - {this.selected ? <FormattedTextBox allowScroll={true} {...fieldProps} /> : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))} + {this.selected ? <FormattedTextBox allowScroll={true} {...fieldProps} DataDoc={this.props.Document} /> : (field => (field ? Field.toString(field) : ''))(FieldValue(fieldProps.Document[fieldProps.fieldKey]))} </div> ); } @@ -311,3 +315,38 @@ export class SchemaBoolCell extends React.Component<SchemaTableCellProps> { ); } } +@observer +export class SchemaEnumerationCell extends React.Component<SchemaTableCellProps> { + @computed get selected() { + const selected: [Doc, number] | undefined = this.props.selectedCell(); + return this.props.isRowActive() && selected?.[0] === this.props.Document && selected[1] === this.props.col; + } + render() { + const { color, textDecoration, fieldProps, cursor, pointerEvents } = SchemaTableCell.renderProps(this.props); + const options = this.props.options?.map(facet => ({ value: facet, label: facet })); + return ( + <div className="schemaSelectionCell" style={{ display: 'flex', color, textDecoration, cursor, pointerEvents }}> + <div style={{ width: '100%' }}> + <Select + styles={{ + menuPortal: base => ({ + ...base, + left: 0, + top: 0, + transform: `translate(${this.props.transform().TranslateX}px, ${this.props.transform().TranslateY}px)`, + width: Number(base.width) * this.props.transform().Scale, + zIndex: 9999, + }), + }} + menuPortalTarget={this.props.menuTarget} + menuPosition={'absolute'} + placeholder={StrCast(this.props.Document[this.props.fieldKey], 'select...')} + options={options} + isMulti={false} + onChange={val => KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), `"${val?.value ?? ''}"`)} + /> + </div> + </div> + ); + } +} |
