diff options
Diffstat (limited to 'src/client/views/collections/CollectionSchemaHeaders.tsx')
-rw-r--r-- | src/client/views/collections/CollectionSchemaHeaders.tsx | 153 |
1 files changed, 95 insertions, 58 deletions
diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index 3d45089a3..d6ebaf8d8 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -2,14 +2,14 @@ import React = require("react"); import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; import "./CollectionSchemaView.scss"; -import { faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare } from '@fortawesome/free-solid-svg-icons'; +import { faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn } from '@fortawesome/free-solid-svg-icons'; import { library, IconProp } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Flyout, anchorPoints } from "../DocumentDecorations"; import { ColumnType } from "./CollectionSchemaView"; import { emptyFunction } from "../../../Utils"; -library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare); +library.add(faPlus, faFont, faHashtag, faAlignJustify, faCheckSquare, faToggleOn); export interface HeaderProps { keyValue: string; @@ -26,7 +26,7 @@ export interface HeaderProps { export class CollectionSchemaHeader extends React.Component<HeaderProps> { render() { let icon: IconProp = this.props.keyType === ColumnType.Number ? "hashtag" : this.props.keyType === ColumnType.String ? "font" : - this.props.keyType === ColumnType.Checkbox || this.props.keyType === ColumnType.Boolean ? "check-square" : "align-justify"; + this.props.keyType === ColumnType.Checkbox ? "check-square" : this.props.keyType === ColumnType.Boolean ? "toggle-on" : "align-justify"; return ( <div className="collectionSchemaView-header" > @@ -67,7 +67,7 @@ export class CollectionSchemaAddColumnHeader extends React.Component<AddColumnHe // } render() { - let addButton = <button onClick={() => console.log("add clicked")}><FontAwesomeIcon icon="plus" size="sm" /></button>; + let addButton = <button><FontAwesomeIcon icon="plus" size="sm" /></button>; return ( <div className="collectionSchemaView-header-addColumn" > {/* {this._creatingColumn ? <></> : */} @@ -76,6 +76,7 @@ export class CollectionSchemaAddColumnHeader extends React.Component<AddColumnHe possibleKeys={this.props.possibleKeys} existingKeys={this.props.existingKeys} keyType={ColumnType.Any} + typeConst={true} menuButtonContent={addButton} addNew={true} onSelect={this.props.onSelect} @@ -120,68 +121,74 @@ export class CollectionSchemaColumnMenu extends React.Component<ColumnMenuProps> this.props.setColumnType(this.props.keyValue, type); } - renderContent = () => { - let keyTypeStr = ColumnType[this.props.keyType]; - let colTypes = []; - for (let type in ColumnType) { - if (!(parseInt(type, 10) >= 0)) colTypes.push(type); - } + renderTypes = () => { + if (this.props.typeConst) return <></>; + return ( + <div className="collectionSchema-headerMenu-group"> + <label>Column type:</label> + <div className="columnMenu-types"> + <button title="Any" className={this.props.keyType === ColumnType.Any ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Any)}> + <FontAwesomeIcon icon={"align-justify"} size="sm" /> + </button> + <button title="Number" className={this.props.keyType === ColumnType.Number ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Number)}> + <FontAwesomeIcon icon={"hashtag"} size="sm" /> + </button> + <button title="String" className={this.props.keyType === ColumnType.String ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.String)}> + <FontAwesomeIcon icon={"font"} size="sm" /> + </button> + <button title="Boolean" className={this.props.keyType === ColumnType.Boolean ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Boolean)}> + <FontAwesomeIcon icon={"toggle-on"} size="sm" /> + </button> + <button title="Checkbox" className={this.props.keyType === ColumnType.Checkbox ? "active" : ""} onClick={() => this.props.setColumnType(this.props.keyValue, ColumnType.Checkbox)}> + <FontAwesomeIcon icon={"check-square"} size="sm" /> + </button> + </div> + </div> + ); + } - if (this._isOpen) { - if (this.props.onlyShowOptions) { - return ( - <div className="collectionSchema-header-menuOptions"> - <KeysDropdown - keyValue={this.props.keyValue} - possibleKeys={this.props.possibleKeys} - existingKeys={this.props.existingKeys} - canAddNew={true} - addNew={this.props.addNew} - onSelect={this.props.onSelect} - /> - </div> - ); - } else { - return ( - <div className="collectionSchema-header-menuOptions"> - <KeysDropdown - keyValue={this.props.keyValue} - possibleKeys={this.props.possibleKeys} - existingKeys={this.props.existingKeys} - canAddNew={true} - addNew={this.props.addNew} - onSelect={this.props.onSelect} - /> - {!this.props.typeConst ? - <KeysDropdown - keyValue={keyTypeStr} - possibleKeys={colTypes} - existingKeys={[]} - canAddNew={false} - addNew={false} - onSelect={this.setColumnType} - /> - : null} + renderContent = () => { + return ( + <div className="collectionSchema-header-menuOptions"> + <label>Key:</label> + <div className="collectionSchema-headerMenu-group"> + <KeysDropdown + keyValue={this.props.keyValue} + possibleKeys={this.props.possibleKeys} + existingKeys={this.props.existingKeys} + canAddNew={true} + addNew={this.props.addNew} + onSelect={this.props.onSelect} + /> + </div> + {this.props.onlyShowOptions ? <></> : + <> + {this.renderTypes()} + <div className="collectionSchema-headerMenu-group"> <button onClick={() => this.props.deleteColumn(this.props.keyValue)}>Delete Column</button> </div> - ); - } - } + </> + } + </div> + ); } render() { return ( - // <Flyout anchorPoint={anchorPoints.TOP} content={<div style={{ color: "black" }}>{this.renderContent()}</div>}> - // <div onClick={() => { this.props.setIsEditing(true); console.log("clicked anchor"); }}>{this.props.menuButton}</div> - // </ Flyout > <div className="collectionSchema-header-menu"> - <div className="collectionSchema-header-toggler" onClick={() => this.toggleIsOpen()}>{this.props.menuButtonContent}</div> - {this.renderContent()} + <Flyout anchorPoint={anchorPoints.TOP_CENTER} content={this.renderContent()}> + <div className="collectionSchema-header-toggler" onClick={() => { this.props.setIsEditing(true); }}>{this.props.menuButtonContent}</div> + </ Flyout > </div> ); } } +{/* // <div className="collectionSchema-header-menu"> + // <div className="collectionSchema-header-toggler" onClick={() => this.toggleIsOpen()}>{this.props.menuButtonContent}</div> + // {this.renderContent()} + // </div> */} + interface KeysDropdownProps { keyValue: string; @@ -190,27 +197,56 @@ interface KeysDropdownProps { canAddNew: boolean; addNew: boolean; onSelect: (oldKey: string, newKey: string, addnew: boolean) => void; - } @observer class KeysDropdown extends React.Component<KeysDropdownProps> { @observable private _key: string = this.props.keyValue; @observable private _searchTerm: string = ""; + @observable private _isOpen: boolean = false; + @observable private _canClose: boolean = true; @action setSearchTerm = (value: string): void => { this._searchTerm = value; }; @action setKey = (key: string): void => { this._key = key; }; + @action setIsOpen = (isOpen: boolean): void => {this._isOpen = isOpen;}; @action onSelect = (key: string): void => { this.props.onSelect(this._key, key, this.props.addNew); this.setKey(key); + this._isOpen = false; } onChange = (val: string): void => { this.setSearchTerm(val); } + @action + onFocus = (e: React.FocusEvent): void => { + this._isOpen = true; + } + + @action + onBlur = (e: React.FocusEvent): void => { + // const that = this; + if (this._canClose) this._isOpen = false; + // setTimeout(function() { // TODO: this might be too hacky lol + // that.setIsOpen(false); + // }, 100); + } + + @action + onPointerEnter = (e: React.PointerEvent): void => { + this._canClose = false; + } + + @action + onPointerOut = (e: React.PointerEvent): void => { + this._canClose = true; + } + renderOptions = (): JSX.Element[] | JSX.Element => { + if (!this._isOpen) return <></>; + let keyOptions = this._searchTerm === "" ? this.props.possibleKeys : this.props.possibleKeys.filter(key => key.toUpperCase().indexOf(this._searchTerm.toUpperCase()) > -1); let exactFound = keyOptions.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1 || this.props.existingKeys.findIndex(key => key.toUpperCase() === this._searchTerm.toUpperCase()) > -1; @@ -222,7 +258,8 @@ class KeysDropdown extends React.Component<KeysDropdownProps> { // if search term does not already exist as a group type, give option to create new group type if (!exactFound && this._searchTerm !== "" && this.props.canAddNew) { options.push(<div key={""} className="key-option" - onClick={() => { this.onSelect(this._searchTerm); this.setSearchTerm(""); }}>Create "{this._searchTerm}" key</div>); + onClick={() => { this.onSelect(this._searchTerm); this.setSearchTerm(""); }}> + Create "{this._searchTerm}" key</div>); } return options; @@ -231,9 +268,9 @@ class KeysDropdown extends React.Component<KeysDropdownProps> { render() { return ( <div className="keys-dropdown"> - <input type="text" value={this._searchTerm} placeholder="Search for or create a new key" - onChange={e => this.onChange(e.target.value)} ></input> - <div className="keys-options-wrapper"> + <input className="keys-search" type="text" value={this._searchTerm} placeholder="Search for or create a new key" + onChange={e => this.onChange(e.target.value)} onFocus={this.onFocus} onBlur={this.onBlur}></input> + <div className="keys-options-wrapper" onPointerEnter={this.onPointerEnter} onPointerOut={this.onPointerOut}> {this.renderOptions()} </div> </div > |