import React = require("react"); import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action } from "mobx"; import { ReactTableDefaults, RowInfo, TableCellRenderer } from "react-table"; import { Doc } from "../../../../fields/Doc"; import { SchemaHeaderField } from "../../../../fields/SchemaHeaderField"; 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}
); } }