blob: 59de0e2b418982c2ef74cb709cff36624026b35c (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
import * as React from 'react';
import "./MetadataEntryMenu.scss";
import { observer } from 'mobx-react';
import { observable, action, runInAction, trace } from 'mobx';
import { KeyValueBox } from './nodes/KeyValueBox';
import { Doc } from '../../new_fields/Doc';
import * as Autosuggest from 'react-autosuggest';
export type DocLike = Doc | Doc[] | Promise<Doc> | Promise<Doc[]>;
export interface MetadataEntryProps {
docs: DocLike | (() => DocLike);
onError?: () => boolean;
suggestWithFunction?: boolean;
}
@observer
export class MetadataEntryMenu extends React.Component<MetadataEntryProps>{
@observable private _currentKey: string = "";
@observable private _currentValue: string = "";
@observable private suggestions: string[] = [];
private autosuggestRef = React.createRef<Autosuggest>();
@action
onKeyChange = (e: React.ChangeEvent, { newValue }: { newValue: string }) => {
this._currentKey = newValue;
}
@action
onValueChange = (e: React.ChangeEvent<HTMLInputElement>) => {
this._currentValue = e.target.value;
}
onValueKeyDown = async (e: React.KeyboardEvent) => {
if (e.key === "Enter") {
const script = KeyValueBox.CompileKVPScript(this._currentValue);
if (!script) return;
let doc = this.props.docs;
if (typeof doc === "function") {
doc = doc();
}
doc = await doc;
let success: boolean;
if (doc instanceof Doc) {
success = KeyValueBox.ApplyKVPScript(doc, this._currentKey, script);
} else {
success = doc.every(d => KeyValueBox.ApplyKVPScript(d, this._currentKey, script));
}
if (!success) {
if (this.props.onError) {
if (this.props.onError()) {
this.clearInputs();
}
} else {
this.clearInputs();
}
} else {
this.clearInputs();
}
}
}
@action
clearInputs = () => {
this._currentKey = "";
this._currentValue = "";
if (this.autosuggestRef.current) {
const input: HTMLInputElement = (this.autosuggestRef.current as any).input;
input && input.focus();
}
}
getKeySuggestions = async (value: string): Promise<string[]> => {
value = value.toLowerCase();
let docs = this.props.docs;
if (typeof docs === "function") {
if (this.props.suggestWithFunction) {
docs = docs();
} else {
return [];
}
}
docs = await docs;
if (docs instanceof Doc) {
return Object.keys(docs).filter(key => key.toLowerCase().startsWith(value));
} else {
const keys = new Set<string>();
docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key)));
return Array.from(keys).filter(key => key.toLowerCase().startsWith(value));
}
}
getSuggestionValue = (suggestion: string) => suggestion;
renderSuggestion = (suggestion: string) => {
return <p>{suggestion}</p>;
}
onSuggestionFetch = async ({ value }: { value: string }) => {
const sugg = await this.getKeySuggestions(value);
runInAction(() => {
this.suggestions = sugg;
});
}
@action
onSuggestionClear = () => {
this.suggestions = [];
}
render() {
trace();
return (
<div className="metadataEntry-outerDiv">
Key:
<Autosuggest inputProps={{ value: this._currentKey, onChange: this.onKeyChange }}
getSuggestionValue={this.getSuggestionValue}
suggestions={this.suggestions}
renderSuggestion={this.renderSuggestion}
onSuggestionsFetchRequested={this.onSuggestionFetch}
onSuggestionsClearRequested={this.onSuggestionClear}
ref={this.autosuggestRef} />
Value:
<input className="metadataEntry-input" value={this._currentValue} onChange={this.onValueChange} onKeyDown={this.onValueKeyDown} />
</div>
);
}
}
|