diff options
Diffstat (limited to 'src/client/views/collections/CollectionSchemaView.tsx')
-rw-r--r-- | src/client/views/collections/CollectionSchemaView.tsx | 183 |
1 files changed, 139 insertions, 44 deletions
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 3ef58bcaf..4746e637b 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -4,7 +4,7 @@ import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; -import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, TableCellRenderer } from "react-table"; +import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults, TableCellRenderer, Column } from "react-table"; import "react-table/react-table.css"; import { emptyFunction, returnFalse, returnZero, returnOne } from "../../../Utils"; import { Doc, DocListCast, DocListCastAsync, Field, FieldResult } from "../../../new_fields/Doc"; @@ -33,12 +33,14 @@ import { undoBatch } from "../../util/UndoManager"; import { timesSeries } from "async"; import { CollectionSchemaHeader, CollectionSchemaAddColumnHeader } from "./CollectionSchemaHeaders"; import { CellProps, CollectionSchemaCell, CollectionSchemaNumberCell, CollectionSchemaStringCell, CollectionSchemaBooleanCell, CollectionSchemaCheckboxCell } from "./CollectionSchemaCells"; - +import { MovableColumn, MovableRow } from "./CollectionSchemaMovableTableHOC"; library.add(faCog); library.add(faPlus); // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 +// const MovableTable = CollectionSchemaMovableSchemaHOC(ReactTable); + export enum ColumnType { Any, Number, @@ -54,22 +56,6 @@ const columnTypes: Map<string, ColumnType> = new Map([ ["page", ColumnType.Number], ["curPage", ColumnType.Number], ["libraryBrush", ColumnType.Boolean], ["zIndex", ColumnType.Number] ]); -// @observer -// class KeyToggle extends React.Component<{ keyName: string, checked: boolean, toggle: (key: string) => void }> { -// constructor(props: any) { -// super(props); -// } - -// render() { -// return ( -// <div key={this.props.keyName}> -// <input type="checkbox" checked={this.props.checked} onChange={() => this.props.toggle(this.props.keyName)} /> -// {this.props.keyName} -// </div> -// ); -// } -// } - @observer export class CollectionSchemaView extends CollectionSubView(doc => doc) { private _mainCont?: HTMLDivElement; @@ -83,6 +69,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @observable _newKeyName: string = ""; @observable previewScript: string = ""; @observable _headerIsEditing: boolean = false; + @observable _cellIsEditing: boolean = false; + @observable _focusedCell: {row: number, col: number} = {row: 0, col: 0}; @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); } @computed get previewHeight() { return () => this.props.PanelHeight() - 2 * this.borderWidth; } @@ -90,10 +78,25 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get columns() { return Cast(this.props.Document.schemaColumns, listSpec("string"), []); } set columns(columns: string[]) { this.props.Document.schemaColumns = new List<string>(columns); } @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } - @computed get tableColumns() { + @computed get tableColumns(): Column<Doc>[] { let possibleKeys = this.documentKeys.filter(key => this.columns.findIndex(existingKey => existingKey.toUpperCase() === key.toUpperCase()) === -1); let cols = this.columns.map(col => { + let focusedRow = this._focusedCell.row; + let focusedCol = this._focusedCell.col; + let isEditable = !this._headerIsEditing; + let header = <CollectionSchemaHeader + keyValue={col} + possibleKeys={possibleKeys} + existingKeys={this.columns} + keyType={this.getColumnType(col)} + typeConst={columnTypes.get(col) !== undefined} + onSelect={this.changeColumns} + setIsEditing={this.setHeaderIsEditing} + deleteColumn={this.deleteColumn} + setColumnType={this.setColumnType} + />; + return { Header: <CollectionSchemaHeader keyValue={col} @@ -106,37 +109,37 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { deleteColumn={this.deleteColumn} setColumnType={this.setColumnType} />, + // Header: <MovableColumn columnRenderer={header} columnValue={col} allColumns={this.columns} reorderColumns={this.reorderColumns} ScreenToLocalTransform={this.props.ScreenToLocalTransform} />, accessor: (doc: Doc) => doc ? doc[col] : 0, id: col, Cell: (rowProps: CellInfo) => { let row = rowProps.index; let column = this.columns.indexOf(rowProps.column.id!); - // let isFocused = focusedRow === row && focusedCol === column; - let isFocused = false; + let isFocused = focusedRow === row && focusedCol === column; let props: CellProps = { row: row, col: column, rowProps: rowProps, isFocused: isFocused, - changeFocusedCellByDirection: action(emptyFunction),//this.changeFocusedCellByDirection, - changeFocusedCellByIndex: action(emptyFunction), //this.changeFocusedCellByIndex, + changeFocusedCellByDirection: this.changeFocusedCellByDirection, + changeFocusedCellByIndex: this.changeFocusedCellByIndex, CollectionView: this.props.CollectionView, ContainingCollection: this.props.ContainingCollectionView, Document: this.props.Document, fieldKey: this.props.fieldKey, renderDepth: this.props.renderDepth, addDocTab: this.props.addDocTab, moveDocument: this.props.moveDocument, - setIsEditing: action(emptyFunction), //this.setCellIsEditing, - isEditable: true //isEditable + setIsEditing: this.setCellIsEditing, + isEditable: isEditable }; let colType = this.getColumnType(col); - if (colType === ColumnType.Number) return <CollectionSchemaNumberCell {...props}/> - if (colType === ColumnType.String) return <CollectionSchemaStringCell {...props}/> - if (colType === ColumnType.Boolean) return <CollectionSchemaBooleanCell {...props} /> - if (colType === ColumnType.Checkbox) return <CollectionSchemaCheckboxCell {...props} /> - return <CollectionSchemaCell {...props}/> + if (colType === ColumnType.Number) return <CollectionSchemaNumberCell {...props}/>; + if (colType === ColumnType.String) return <CollectionSchemaStringCell {...props}/>; + if (colType === ColumnType.Boolean) return <CollectionSchemaBooleanCell {...props} />; + if (colType === ColumnType.Checkbox) return <CollectionSchemaCheckboxCell {...props} />; + return <CollectionSchemaCell {...props}/>; } }; }) as {Header: TableCellRenderer, accessor: (doc: Doc) => FieldResult<Field>, id: string, Cell: (rowProps: CellInfo) => JSX.Element}[]; @@ -156,6 +159,19 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return cols; } + reorderColumns(toMove: string, relativeTo: string, before: boolean, columnsValues: string[]) { + let columns = [...columnsValues]; + let oldIndex = columns.indexOf(toMove); + let relIndex = columns.indexOf(relativeTo); + let newIndex = (oldIndex > relIndex && !before) ? relIndex + 1 : (oldIndex < relIndex && before) ? relIndex - 1 : relIndex; + + if (oldIndex === newIndex) return; + + columns.splice(newIndex, 0, columns.splice(oldIndex, 1)[0]); + this.columns = columns; + } + + onHeaderDrag = (columnName: string) => { let schemaDoc = Cast(this.props.Document.schemaDoc, Doc); if (schemaDoc instanceof Doc) { @@ -170,12 +186,21 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return this.props.Document; } + componentDidMount() { + document.addEventListener("keydown", this.onKeyDown); + } + + componentWillUnmount() { + document.removeEventListener("keydown", this.onKeyDown); + } + private getTrProps: ComponentPropsGetterR = (state, rowInfo) => { const that = this; if (!rowInfo) { return {}; } return { + rowInfo, onClick: action((e: React.MouseEvent, handleOriginal: Function) => { that.props.select(e.ctrlKey); that._selectedIndex = rowInfo.index; @@ -195,27 +220,63 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { this._mainCont = ele; super.CreateDropTarget(ele); } + @action + changeFocusedCellByDirection = (direction: string): void => { + switch (direction) { + case "tab": + if (this._focusedCell.col + 1 === this.columns.length && this._focusedCell.row + 1 === this.childDocs.length) { + this._focusedCell = { row: 0, col: 0 }; + } else if (this._focusedCell.col + 1 === this.columns.length) { + this._focusedCell = { row: this._focusedCell.row + 1, col: 0 }; + } else { + this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col + 1 }; + } + break; + case "right": + this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col + 1 === this.columns.length ? this._focusedCell.col : this._focusedCell.col + 1 }; + break; + case "left": + this._focusedCell = { row: this._focusedCell.row, col: this._focusedCell.col === 0 ? this._focusedCell.col : this._focusedCell.col - 1 }; + break; + case "up": + this._focusedCell = { row: this._focusedCell.row === 0 ? this._focusedCell.row : this._focusedCell.row - 1, col: this._focusedCell.col }; + break; + case "down": + this._focusedCell = { row: this._focusedCell.row + 1 === this.childDocs.length ? this._focusedCell.row : this._focusedCell.row + 1, col: this._focusedCell.col }; + break; + } + } @action - setHeaderIsEditing = (isEditing: boolean) => { - this._headerIsEditing = isEditing; + changeFocusedCellByIndex = (row: number, col: number): void => { + this._focusedCell = { row: row, col: col }; } @action - toggleKey = (key: string) => { - let list = Cast(this.props.Document.schemaColumns, listSpec("string")); - if (list === undefined) { - this.props.Document.schemaColumns = list = new List<string>([key]); - } else { - const index = list.indexOf(key); - if (index === -1) { - list.push(key); - } else { - list.splice(index, 1); - } - } + setCellIsEditing = (isEditing: boolean): void => { + this._cellIsEditing = isEditing; } + @action + setHeaderIsEditing = (isEditing: boolean): void => { + this._headerIsEditing = isEditing; + } + + // @action + // toggleKey = (key: string) => { + // let list = Cast(this.props.Document.schemaColumns, listSpec("string")); + // if (list === undefined) { + // this.props.Document.schemaColumns = list = new List<string>([key]); + // } else { + // const index = list.indexOf(key); + // if (index === -1) { + // list.push(key); + // } else { + // list.splice(index, 1); + // } + // } + // } + //toggles preview side-panel of schema @action toggleExpander = () => { @@ -262,6 +323,13 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } } + onKeyDown = (e: KeyboardEvent): void => { + if (!this._cellIsEditing && !this._headerIsEditing) { + let direction = e.key === "Tab" ? "tab" : e.which === 39 ? "right" : e.which === 37 ? "left" : e.which === 38 ? "up" : e.which === 40 ? "down" : ""; + this.changeFocusedCellByDirection(direction); + } + } + @action makeDB = async () => { let csv: string = this.columns.reduce((val, col) => val + col + ",", ""); @@ -410,7 +478,31 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @computed get reactTable() { + 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); let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; + + // return <MovableTable + // style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }} + // data={this.childDocs} + // page={0} + // pageSize={this.childDocs.length} + // showPagination={false} + // columns={this.tableColumns} + // sortable={false} + // getTrProps={this.getTrProps} + + // ScreenToLocalTransform={this.props.ScreenToLocalTransform} + // addDoc={addDoc} + // moveDoc={moveDoc} + // columnsValues={this.columns} + // columnsList={this.tableColumns} + // setColumnsOrder={(columns: string[]) => this.columns = columns} + // numImmovableColumns={1} + // />; + + + // // let previewWidth = this.previewWidth() + 2 * this.borderWidth + this.DIVIDER_WIDTH + 1; return <ReactTable style={{ position: "relative", float: "left", width: `calc(100% - ${previewWidth}px` }} data={this.childDocs} @@ -421,6 +513,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { // column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }} getTrProps={this.getTrProps} sortable={false} + + TrComponent={MovableRow(this.props.ScreenToLocalTransform, addDoc, moveDoc)} />; } @@ -472,6 +566,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { return ( <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}> + <div draggable={true} style={{backgroundColor: "green"}}>TESTER</div> {this.reactTable} {this.dividerDragger} {!this.previewWidth() ? (null) : this.previewPanel} |