aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/KeywordBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/KeywordBox.tsx')
-rw-r--r--src/client/views/KeywordBox.tsx168
1 files changed, 137 insertions, 31 deletions
diff --git a/src/client/views/KeywordBox.tsx b/src/client/views/KeywordBox.tsx
index 3faddeb64..8c69f446d 100644
--- a/src/client/views/KeywordBox.tsx
+++ b/src/client/views/KeywordBox.tsx
@@ -1,64 +1,170 @@
-import { action, makeObservable } from 'mobx';
+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>;
+ }
+ };
+
+ 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;
+ 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;
+ this._props.isEditing = true;
};
@action
setToView = () => {
- this._props._isEditing = false;
+ this._props.isEditing = false;
};
- submitLabel = () => {};
+ submitLabel = () => {
+ if (this._currentInput.trim()) {
+ if (!this._props.doc[DocData].data_labels) {
+ this._props.doc[DocData].data_labels = new List<string>();
+ }
- onInputChange = () => {};
+ (this._props.doc![DocData].data_labels! as List<string>).push(this._currentInput.trim());
+ 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;
+ 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">
- {(keywordsList as List<string>).map(label => {
- return (
- <div className="keyword" onClick={this.setToEditing}>
- {label}
+ <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>
- );
- })}
- {this._props._isEditing ? (
- <div>
- <input
- defaultValue=""
- 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></div>