diff options
Diffstat (limited to 'src/client/views/KeywordBox.tsx')
-rw-r--r-- | src/client/views/KeywordBox.tsx | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/src/client/views/KeywordBox.tsx b/src/client/views/KeywordBox.tsx new file mode 100644 index 000000000..d94f011f4 --- /dev/null +++ b/src/client/views/KeywordBox.tsx @@ -0,0 +1,177 @@ +import { Colors, IconButton } from 'browndash-components'; +import { action, computed, makeObservable, observable, reaction } from 'mobx'; +import { observer } from 'mobx-react'; +import React from 'react'; +import { Doc } from '../../fields/Doc'; +import { DocData } from '../../fields/DocSymbols'; +import { List } from '../../fields/List'; +import { DragManager, SetupDrag } from '../util/DragManager'; +import { SnappingManager } from '../util/SnappingManager'; +import { DocumentView } from './nodes/DocumentView'; +import { ObservableReactComponent } from './ObservableReactComponent'; + +interface KeywordItemProps { + doc: Doc; + label: string; + setToEditing: () => void; + isEditing: boolean; +} + +@observer +export class KeywordItem extends ObservableReactComponent<KeywordItemProps> { + constructor(props: any) { + super(props); + makeObservable(this); + this.ref = React.createRef(); + } + + private _dropDisposer?: DragManager.DragDropDisposer; + private ref: React.RefObject<HTMLDivElement>; + + protected createDropTarget = (ele: HTMLDivElement) => { + this._dropDisposer?.(); + SetupDrag(this.ref, () => undefined); + //ele && (this._dropDisposer = DragManager. (ele, this.onInternalDrop.bind(this), this.layoutDoc)); + //ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc)); + }; + + @action + removeLabel = () => { + if (this._props.doc[DocData].data_labels) { + this._props.doc[DocData].data_labels = (this._props.doc[DocData].data_labels as List<string>).filter(label => label !== this._props.label) as List<string>; + this._props.doc![DocData][`${this._props.label}`] = false; + } + }; + + render() { + return ( + <div className="keyword" onClick={this._props.setToEditing} onPointerDown={() => {}} ref={this.ref}> + {this._props.label} + {this.props.isEditing && <IconButton tooltip={'Remove label'} onPointerDown={this.removeLabel} icon={'X'} style={{ width: '8px', height: '8px', marginLeft: '10px' }} />} + </div> + ); + } +} + +interface KeywordBoxProps { + doc: Doc; + isEditing: boolean; +} + +@observer +export class KeywordBox extends ObservableReactComponent<KeywordBoxProps> { + @observable _currentInput: string = ''; + //private disposer: () => void; + + constructor(props: any) { + super(props); + makeObservable(this); + } + + // componentDidMount(): void { + // reaction( + // () => ({ + // isDragging: SnappingManager.IsDragging, + // selectedDoc: DocumentView.SelectedDocs().lastElement(), + // isEditing: this._props.isEditing, + // }), + // ({ isDragging, selectedDoc, isEditing }) => { + // if (isDragging || selectedDoc !== this._props.doc || !isEditing) { + // this.setToView(); + // } + // } + // ); + // } + + // componentWillUnmount() { + // this.disposer(); + // } + + @action + setToEditing = () => { + this._props.isEditing = true; + }; + + @action + setToView = () => { + this._props.isEditing = false; + }; + + submitLabel = () => { + if (this._currentInput.trim()) { + if (!this._props.doc[DocData].data_labels) { + this._props.doc[DocData].data_labels = new List<string>(); + } + + (this._props.doc![DocData].data_labels! as List<string>).push(this._currentInput.trim()); + this._props.doc![DocData][`${this._currentInput}`] = true; + this._currentInput = ''; // Clear the input box + } + }; + + @action + onInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { + this._currentInput = e.target.value; + }; + + render() { + const keywordsList = this._props.doc[DocData].data_labels ? this._props.doc[DocData].data_labels : new List<string>(); + const seldoc = DocumentView.SelectedDocs().lastElement(); + if (SnappingManager.IsDragging || !(seldoc === this._props.doc) || !this._props.isEditing) { + setTimeout( + action(() => { + if ((keywordsList as List<string>).length === 0) { + this._props.doc[DocData].showLabels = false; + } + this.setToView(); + }) + ); + } + + return ( + <div className="keywords-container" style={{ backgroundColor: this._props.isEditing ? Colors.LIGHT_GRAY : Colors.TRANSPARENT, borderColor: this._props.isEditing ? Colors.BLACK : Colors.TRANSPARENT }}> + <div className="keywords-list"> + {(keywordsList as List<string>).map(label => { + return <KeywordItem doc={this._props.doc} label={label} setToEditing={this.setToEditing} isEditing={this._props.isEditing}></KeywordItem>; + })} + </div> + {this._props.isEditing ? ( + <div className="keyword-editing-box"> + <div className="keyword-input-box"> + <input + value={this._currentInput} + autoComplete="off" + onChange={this.onInputChange} + onKeyDown={e => { + e.key === 'Enter' ? this.submitLabel() : null; + e.stopPropagation(); + }} + type="text" + placeholder="Input keywords for document..." + aria-label="keyword-input" + className="keyword-input" + style={{ width: '100%', borderRadius: '5px' }} + /> + </div> + <div className="keyword-buttons"> + <IconButton + tooltip={'Close Menu'} + onPointerDown={() => { + if ((keywordsList as List<string>).length === 0) { + this._props.doc[DocData].showLabels = false; + } else { + this.setToView(); + } + }} + icon={'x'} + style={{ width: '4px' }} + /> + </div> + </div> + ) : ( + <div></div> + )} + </div> + ); + } +} |