diff options
Diffstat (limited to 'src/client/views/nodes/KeyValueBox.tsx')
-rw-r--r-- | src/client/views/nodes/KeyValueBox.tsx | 114 |
1 files changed, 97 insertions, 17 deletions
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index ac8c949a9..86437a6c1 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -1,18 +1,54 @@ +import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app -import { Document } from '../../../fields/Document'; -import { FieldWaiting } from '../../../fields/Field'; -import { KeyStore } from '../../../fields/KeyStore'; +import { CompileScript } from "../../util/Scripting"; import { FieldView, FieldViewProps } from './FieldView'; import "./KeyValueBox.scss"; import { KeyValuePair } from "./KeyValuePair"; -import React = require("react") +import React = require("react"); +import { NumCast, Cast, FieldValue } from "../../../new_fields/Types"; +import { Doc, IsField } from "../../../new_fields/Doc"; @observer export class KeyValueBox extends React.Component<FieldViewProps> { + private _mainCont = React.createRef<HTMLDivElement>(); - public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(KeyValueBox, fieldStr) } + public static LayoutString(fieldStr: string = "data") { return FieldView.LayoutString(KeyValueBox, fieldStr); } + @observable private _keyInput: string = ""; + @observable private _valueInput: string = ""; + @computed get splitPercentage() { return NumCast(this.props.Document.schemaSplitPercentage, 50); } + get fieldDocToLayout() { return this.props.fieldKey ? FieldValue(Cast(this.props.Document[this.props.fieldKey], Doc)) : this.props.Document; } + + constructor(props: FieldViewProps) { + super(props); + } + + @action + onEnterKey = (e: React.KeyboardEvent): void => { + if (e.key === 'Enter') { + if (this._keyInput && this._valueInput) { + let doc = this.fieldDocToLayout; + if (!doc) { + return; + } + let realDoc = doc; + + let script = CompileScript(this._valueInput, { addReturn: true }); + if (!script.compiled) { + return; + } + let res = script.run(); + if (!res.success) return; + const field = res.result; + if (IsField(field)) { + realDoc[this._keyInput] = field; + } + this._keyInput = ""; + this._valueInput = ""; + } + } + } onPointerDown = (e: React.PointerEvent): void => { if (e.buttons === 1 && this.props.isSelected()) { @@ -24,43 +60,87 @@ export class KeyValueBox extends React.Component<FieldViewProps> { } createTable = () => { - let doc = this.props.doc.GetT(KeyStore.Data, Document); - if (!doc || doc == FieldWaiting) { - return <tr><td>Loading...</td></tr> + let doc = this.fieldDocToLayout; + if (!doc) { + return <tr><td>Loading...</td></tr>; } let realDoc = doc; let ids: { [key: string]: string } = {}; - let protos = doc.GetAllPrototypes(); + let protos = Doc.GetAllPrototypes(doc); for (const proto of protos) { - proto._proxies.forEach((val, key) => { + Object.keys(proto).forEach(key => { if (!(key in ids)) { ids[key] = key; } - }) + }); } let rows: JSX.Element[] = []; let i = 0; for (let key in ids) { - rows.push(<KeyValuePair doc={realDoc} rowStyle={"keyValueBox-" + (i++ % 2 ? "oddRow" : "evenRow")} fieldId={key} key={key} />) + rows.push(<KeyValuePair doc={realDoc} keyWidth={100 - this.splitPercentage} rowStyle={"keyValueBox-" + (i++ % 2 ? "oddRow" : "evenRow")} key={key} keyName={key} />); } return rows; } + @action + keyChanged = (e: React.ChangeEvent<HTMLInputElement>) => { + this._keyInput = e.currentTarget.value; + } + + @action + valueChanged = (e: React.ChangeEvent<HTMLInputElement>) => { + this._valueInput = e.currentTarget.value; + } + + newKeyValue = () => + ( + <tr className="keyValueBox-valueRow"> + <td className="keyValueBox-td-key" style={{ width: `${100 - this.splitPercentage}%` }}> + <input style={{ width: "100%" }} type="text" value={this._keyInput} placeholder="Key" onChange={this.keyChanged} /> + </td> + <td className="keyValueBox-td-value" style={{ width: `${this.splitPercentage}%` }}> + <input style={{ width: "100%" }} type="text" value={this._valueInput} placeholder="Value" onChange={this.valueChanged} onKeyPress={this.onEnterKey} /> + </td> + </tr> + ) + + @action + onDividerMove = (e: PointerEvent): void => { + let nativeWidth = this._mainCont.current!.getBoundingClientRect(); + this.props.Document.schemaSplitPercentage = Math.max(0, 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); + } + onDividerDown = (e: React.PointerEvent) => { + e.stopPropagation(); + e.preventDefault(); + document.addEventListener("pointermove", this.onDividerMove); + document.addEventListener('pointerup', this.onDividerUp); + } render() { + let dividerDragger = this.splitPercentage === 0 ? (null) : + <div className="keyValueBox-dividerDragger" style={{ transform: `translate(calc(${100 - this.splitPercentage}% - 5px), 0px)` }}> + <div className="keyValueBox-dividerDraggerThumb" onPointerDown={this.onDividerDown} /> + </div>; - return (<div className="keyValueBox-cont" onWheel={this.onPointerWheel}> + return (<div className="keyValueBox-cont" onWheel={this.onPointerWheel} ref={this._mainCont}> <table className="keyValueBox-table"> - <tbody> + <tbody className="keyValueBox-tbody"> <tr className="keyValueBox-header"> - <th>Key</th> - <th>Fields</th> + <th className="keyValueBox-key" style={{ width: `${100 - this.splitPercentage}%` }}>Key</th> + <th className="keyValueBox-fields" style={{ width: `${this.splitPercentage}%` }}>Fields</th> </tr> {this.createTable()} + {this.newKeyValue()} </tbody> </table> - </div>) + {dividerDragger} + </div>); } }
\ No newline at end of file |