import React = require("react") import { action, observable, ObservableMap, computed } from "mobx"; import { observer } from "mobx-react"; import Measure from "react-measure"; import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table"; import "react-table/react-table.css"; import { Document } from "../../../fields/Document"; import { Field, Opt } from "../../../fields/Field"; import { KeyStore } from "../../../fields/KeyStore"; import { CompileScript, ToField } from "../../util/Scripting"; import { Transform } from "../../util/Transform"; import { EditableView } from "../EditableView"; import { DocumentView } from "../nodes/DocumentView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./CollectionSchemaView.scss"; import { COLLECTION_BORDER_WIDTH, CollectionView } from "./CollectionView"; import { CollectionViewBase } from "./CollectionViewBase"; import { setupDrag } from "../../util/DragManager"; import { Key } from "./../../../fields/Key"; import { Server } from "../../Server"; import { ListField } from "../../../fields/ListField"; // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 @observer class KeyToggle extends React.Component<{ keyId: string, checked: boolean, toggle: (key: Key) => void }> { @observable key: Key | undefined; componentWillReceiveProps() { Server.GetField(this.props.keyId, action((field: Opt) => { if (field instanceof Key) { this.key = field; } })) } render() { if (this.key) { return (
this.key && this.props.toggle(this.key)} />{this.key.Name}
) } else { return
} } } @observer export class CollectionSchemaView extends CollectionViewBase { private _mainCont = React.createRef(); private DIVIDER_WIDTH = 4; @observable _columns: Array = [KeyStore.Title, KeyStore.Data, KeyStore.Author]; @observable _contentScaling = 1; // used to transfer the dimensions of the content pane in the DOM to the ContentScaling prop of the DocumentView @observable _dividerX = 0; @observable _panelWidth = 0; @observable _panelHeight = 0; @observable _selectedIndex = 0; @observable _columnsPercentage = 0; @computed get splitPercentage() { return this.props.Document.GetNumber(KeyStore.SchemaSplitPercentage, 0); } renderCell = (rowProps: CellInfo) => { let props: FieldViewProps = { doc: rowProps.value[0], fieldKey: rowProps.value[1], isSelected: () => false, select: () => { }, isTopMost: false, bindings: {}, selectOnLoad: false, } let contents = ( ) let reference = React.createRef(); let onItemDown = setupDrag(reference, () => props.doc, (containingCollection: CollectionView) => this.props.removeDocument(props.doc)); return (
{ let field = props.doc.Get(props.fieldKey); if (field && field instanceof Field) { return field.ToScriptString(); } return field || ""; }} SetValue={(value: string) => { let script = CompileScript(value); if (!script.compiled) { return false; } let field = script(); if (field instanceof Field) { props.doc.Set(props.fieldKey, field); return true; } else { let dataField = ToField(field); if (dataField) { props.doc.Set(props.fieldKey, dataField); return true; } } return false; }}>
) } private getTrProps: ComponentPropsGetterR = (state, rowInfo) => { const that = this; if (!rowInfo) { return {}; } return { onClick: action((e: React.MouseEvent, handleOriginal: Function) => { that._selectedIndex = rowInfo.index; // bcz - ugh - needed to force Measure to do its thing and call onResize this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage - 0.05) if (handleOriginal) { handleOriginal() } }), style: { background: rowInfo.index == this._selectedIndex ? "lightGray" : "white", //color: rowInfo.index == this._selectedIndex ? "white" : "black" } }; } get columns() { return this.props.Document.GetList(KeyStore.ColumnsKey, []); } @action toggleKey = (key: Key) => { this.props.Document.GetOrCreateAsync>(KeyStore.ColumnsKey, ListField, (field) => { const index = field.Data.indexOf(key); if (index === -1) { this.columns.push(key); } else { this.columns.splice(index, 1); } }) } @observable keys: Key[] = []; findAllDocumentKeys = (): { [id: string]: boolean } => { const docs = this.props.Document.GetList(this.props.fieldKey, []); let keys: { [id: string]: boolean } = {} docs.forEach(doc => { let protos = doc.GetAllPrototypes(); for (const proto of protos) { proto._proxies.forEach((val: any, key: string) => { keys[key] = false }) } }) this.columns.forEach(key => { keys[key.Id] = true; }) return keys; } _startSplitPercent = 0; @action onDividerMove = (e: PointerEvent): void => { let nativeWidth = this._mainCont.current!.getBoundingClientRect(); this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, 100 - Math.round((e.clientX - nativeWidth.left) / nativeWidth.width * 100)); } @action onDividerUp = (e: PointerEvent): void => { document.removeEventListener("pointermove", this.onDividerMove); document.removeEventListener('pointerup', this.onDividerUp); if (this._startSplitPercent == this.splitPercentage) { this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage == 0 ? 33 : 0); } } onDividerDown = (e: React.PointerEvent) => { this._startSplitPercent = this.splitPercentage; e.stopPropagation(); e.preventDefault(); document.addEventListener("pointermove", this.onDividerMove); document.addEventListener('pointerup', this.onDividerUp); } @action onColDividerMove = (e: PointerEvent): void => { let nativeWidth = this._mainCont.current!.getBoundingClientRect(); this._columnsPercentage = 100 - (e.clientY - nativeWidth.top) / nativeWidth.height * 100; } @action onColDividerUp = (e: PointerEvent): void => { document.removeEventListener("pointermove", this.onColDividerMove); document.removeEventListener('pointerup', this.onColDividerUp); } onColDividerDown = (e: React.PointerEvent) => { e.stopPropagation(); e.preventDefault(); document.addEventListener("pointermove", this.onColDividerMove); document.addEventListener('pointerup', this.onColDividerUp); } @action onExpanderMove = (e: PointerEvent): void => { e.stopPropagation(); e.preventDefault(); } @action onExpanderUp = (e: PointerEvent): void => { e.stopPropagation(); e.preventDefault(); document.removeEventListener("pointermove", this.onExpanderMove); document.removeEventListener('pointerup', this.onExpanderUp); if (this._startSplitPercent == this.splitPercentage) { this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage == 0 ? 33 : 0); } } onExpanderDown = (e: React.PointerEvent) => { this._startSplitPercent = this.splitPercentage; e.stopPropagation(); e.preventDefault(); document.addEventListener("pointermove", this.onExpanderMove); document.addEventListener('pointerup', this.onExpanderUp); } onPointerDown = (e: React.PointerEvent) => { // if (e.button === 2 && this.active) { // e.stopPropagation(); // e.preventDefault(); // } else { // if (e.buttons === 1) { // if (this.props.isSelected()) { // e.stopPropagation(); // } // } } } @action onColumnsMove = (e: PointerEvent): void => { e.stopPropagation(); e.preventDefault(); } @action onColumnsUp = (e: PointerEvent): void => { e.stopPropagation(); e.preventDefault(); document.removeEventListener("pointermove", this.onColumnsMove); document.removeEventListener('pointerup', this.onColumnsUp); this._columnsPercentage = this._columnsPercentage ? 0 : 50; } onColumnsDown = (e: React.PointerEvent) => { this._startSplitPercent = this.splitPercentage; e.stopPropagation(); e.preventDefault(); document.addEventListener("pointermove", this.onColumnsMove); document.addEventListener('pointerup', this.onColumnsUp); } @action setScaling = (r: any) => { const children = this.props.Document.GetList(this.props.fieldKey, []); const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined; this._panelWidth = r.entry.width; this._panelHeight = r.entry.height ? r.entry.height : this._panelHeight; this._contentScaling = r.entry.width / selected!.GetNumber(KeyStore.NativeWidth, r.entry.width); } getContentScaling = (): number => this._contentScaling; getPanelWidth = (): number => this._panelWidth; getPanelHeight = (): number => this._panelHeight; getTransform = (): Transform => { return this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling); } focusDocument = (doc: Document) => { } render() { const columns = this.columns; const children = this.props.Document.GetList(this.props.fieldKey, []); const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined; const allKeys = this.findAllDocumentKeys(); let content = this._selectedIndex == -1 || !selected ? (null) : ( {({ measureRef }) =>
}
) let previewHandle = !this.props.active() ? (null) : (
); let columnsHandle = !this.props.active() ? (null) : (
); let dividerDragger = this.splitPercentage == 0 ? (null) :
let colDividerDragger = this._columnsPercentage == 0 ? (null) :
return (
this.onDrop(e, {})} ref={this.createDropTarget}> { this._dividerX = r.entry.width; this._panelHeight = r.entry.height; })}> {({ measureRef }) =>
({ Header: col.Name, accessor: (doc: Document) => [doc, col], id: col.Id }))} column={{ ...ReactTableDefaults.column, Cell: this.renderCell, }} getTrProps={this.getTrProps} />
{colDividerDragger}
{/* */}
    {Array.from(Object.keys(allKeys)).map(item => { return () })}
}
{dividerDragger}
{content}
{previewHandle} {columnsHandle}
) } }