import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action } from 'mobx'; import * as React from 'react'; import { ReactTableDefaults, RowInfo } from 'react-table'; import { Doc } from '../../../../fields/Doc'; import { Cast, FieldValue, StrCast } from '../../../../fields/Types'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager, dropActionType, SetupDrag } from '../../../util/DragManager'; import { SnappingManager } from '../../../util/SnappingManager'; import { Transform } from '../../../util/Transform'; import { undoBatch } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; import './CollectionSchemaView.scss'; export interface MovableRowProps { rowInfo: RowInfo; ScreenToLocalTransform: () => Transform; addDoc: (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => boolean; removeDoc: (doc: Doc | Doc[]) => boolean; rowFocused: boolean; textWrapRow: (doc: Doc) => void; rowWrapped: boolean; dropAction: string; addDocTab: any; } export class MovableRow extends React.Component> { private _header?: React.RefObject = React.createRef(); private _rowDropDisposer?: DragManager.DragDropDisposer; // Event listeners are only necessary when the user is hovering over the table // Create one when the mouse starts hovering... onPointerEnter = (e: React.PointerEvent): void => { if (e.buttons === 1 && SnappingManager.GetIsDragging()) { this._header!.current!.className = 'collectionSchema-row-wrapper'; document.addEventListener('pointermove', this.onDragMove, true); } }; // ... and delete it when the mouse leaves onPointerLeave = (e: React.PointerEvent): void => { this._header!.current!.className = 'collectionSchema-row-wrapper'; document.removeEventListener('pointermove', this.onDragMove, true); }; // The method for the event listener, reorders columns when dragged to their new locations. onDragMove = (e: PointerEvent): void => { const x = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY); const rect = this._header!.current!.getBoundingClientRect(); const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); const before = x[1] < bounds[1]; this._header!.current!.className = 'collectionSchema-row-wrapper'; if (before) this._header!.current!.className += ' row-above'; if (!before) this._header!.current!.className += ' row-below'; e.stopPropagation(); }; componentWillUnmount() { this._rowDropDisposer?.(); } // createRowDropTarget = (ele: HTMLDivElement) => { this._rowDropDisposer?.(); if (ele) { this._rowDropDisposer = DragManager.MakeDropTarget(ele, this.rowDrop.bind(this)); } }; // Controls what hppens when a row is dragged and dropped rowDrop = (e: Event, de: DragManager.DropEvent) => { this.onPointerLeave(e as any); const rowDoc = FieldValue(Cast(this.props.rowInfo.original, Doc)); if (!rowDoc) return false; const x = this.props.ScreenToLocalTransform().transformPoint(de.x, de.y); const rect = this._header!.current!.getBoundingClientRect(); const bounds = this.props.ScreenToLocalTransform().transformPoint(rect.left, rect.top + rect.height / 2); const before = x[1] < bounds[1]; const docDragData = de.complete.docDragData; if (docDragData) { e.stopPropagation(); if (docDragData.draggedDocuments[0] === rowDoc) return true; const addDocument = (doc: Doc | Doc[]) => this.props.addDoc(doc, rowDoc, before); const movedDocs = docDragData.draggedDocuments; return docDragData.dropAction || docDragData.userDropAction ? docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before) || added, false) : docDragData.moveDocument ? movedDocs.reduce((added: boolean, d) => docDragData.moveDocument?.(d, rowDoc, addDocument) || added, false) : docDragData.droppedDocuments.reduce((added: boolean, d) => this.props.addDoc(d, rowDoc, before), false); } return false; }; onRowContextMenu = (e: React.MouseEvent): void => { const description = this.props.rowWrapped ? 'Unwrap text on row' : 'Text wrap row'; ContextMenu.Instance.addItem({ description: description, event: () => this.props.textWrapRow(this.props.rowInfo.original), icon: 'file-pdf' }); }; @undoBatch @action move: DragManager.MoveFunction = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDoc) => { const targetView = targetCollection && DocumentManager.Instance.getDocumentView(targetCollection); return doc !== targetCollection && doc !== targetView?.props.ContainingCollectionDoc && this.props.removeDoc(doc) && addDoc(doc); }; @action onKeyDown = (e: React.KeyboardEvent) => { console.log('yes'); if (e.key === 'Backspace' || e.key === 'Delete') { undoBatch(() => this.props.removeDoc(this.props.rowInfo.original)); } }; render() { const { children = null, rowInfo } = this.props; if (!rowInfo) { return {children}; } const { original } = rowInfo; const doc = FieldValue(Cast(original, Doc)); if (!doc) return null; const reference = React.createRef(); const onItemDown = SetupDrag(reference, () => doc, this.move, StrCast(this.props.dropAction) as dropActionType); let className = 'collectionSchema-row'; if (this.props.rowFocused) className += ' row-focused'; if (this.props.rowWrapped) className += ' row-wrapped'; return (
this.props.removeDoc(this.props.rowInfo.original))}>
this.props.addDocTab(this.props.rowInfo.original, 'add:right')}>
{children}
); } }