Tag autocomplete behavior fix
This commit is contained in:
parent
89809ad197
commit
b75564b29f
|
@ -5,14 +5,21 @@ const Autocomplete = props => {
|
|||
|
||||
const element = useRef();
|
||||
|
||||
const [ value, setValue ] = useState('');
|
||||
|
||||
const [ inputItems, setInputItems ] = useState(props.vocabulary);
|
||||
|
||||
useEffect(() =>
|
||||
element.current?.querySelector('input').focus(), []);
|
||||
useEffect(() => element.current?.querySelector('input')?.focus(), []);
|
||||
|
||||
const onSubmit = inputValue => {
|
||||
setValue('');
|
||||
setInputItems([]); // Force-hide the popup
|
||||
if (inputValue.trim().length > 0)
|
||||
props.onSubmit(inputValue);
|
||||
}
|
||||
|
||||
const onInputValueChange = ({ inputValue }) => {
|
||||
props.onChange(inputValue);
|
||||
|
||||
setValue(inputValue);
|
||||
setInputItems(
|
||||
props.vocabulary.filter(item =>
|
||||
item.toLowerCase().startsWith(inputValue.toLowerCase())))
|
||||
|
@ -25,19 +32,23 @@ const Autocomplete = props => {
|
|||
getComboboxProps,
|
||||
highlightedIndex,
|
||||
getItemProps,
|
||||
} = useCombobox({ items: inputItems, onInputValueChange });
|
||||
|
||||
// TODO onEnter?
|
||||
const onKeyDown = evt => {
|
||||
if (evt.which == 13) {
|
||||
if (!isOpen || highlightedIndex == -1) {
|
||||
setInputItems([]); // To prevent the popup from showing up afterwards
|
||||
props.onKeyDown(evt);
|
||||
}
|
||||
} else if (evt.which == 40 && props.content.length == 0) {
|
||||
// To make options appear on key down
|
||||
setInputItems(props.vocabulary);
|
||||
setInputValue
|
||||
} = useCombobox({
|
||||
items: inputItems,
|
||||
onInputValueChange,
|
||||
onSelectedItemChange: ({ inputValue }) => {
|
||||
onSubmit(inputValue);
|
||||
setInputValue('');
|
||||
}
|
||||
});
|
||||
|
||||
const onKeyDown = evt => {
|
||||
if (evt.which == 13 && highlightedIndex == -1)
|
||||
onSubmit(value);
|
||||
else if (evt.which == 40 && value.length == 0)
|
||||
setInputItems(props.vocabulary); // Show all options on key down
|
||||
else if (evt.which == 27)
|
||||
props.onCancel && props.onCancel();
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -46,7 +57,8 @@ const Autocomplete = props => {
|
|||
<input
|
||||
{...getInputProps({ onKeyDown })}
|
||||
placeholder={props.placeholder}
|
||||
value={props.content} />
|
||||
defaultValue={props.initialValue}
|
||||
value={value} />
|
||||
</div>
|
||||
<ul {...getMenuProps()}>
|
||||
{isOpen && inputItems.map((item, index) => (
|
||||
|
|
|
@ -9,7 +9,6 @@ import Autocomplete from '../Autocomplete';
|
|||
const TagWidget = props => {
|
||||
|
||||
const [ showDelete, setShowDelete ] = useState(false);
|
||||
const [ newTag, setNewTag ] = useState('');
|
||||
|
||||
// Every body with a 'tagging' purpose is considered a tag
|
||||
const tagBodies = props.annotation ?
|
||||
|
@ -27,11 +26,8 @@ const TagWidget = props => {
|
|||
props.onRemoveBody(tag);
|
||||
}
|
||||
|
||||
const onKeyDown = evt => {
|
||||
if (evt.which === 13) { // Enter
|
||||
props.onAppendBody({ type: 'TextualBody', purpose: 'tagging', value: newTag.trim() });
|
||||
setNewTag(''); // Clear the input
|
||||
}
|
||||
const onSubmit = tag => {
|
||||
props.onAppendBody({ type: 'TextualBody', purpose: 'tagging', value: tag.trim() });
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -58,10 +54,8 @@ const TagWidget = props => {
|
|||
|
||||
{ !props.readOnly &&
|
||||
<Autocomplete
|
||||
content={newTag}
|
||||
placeholder={i18n.t('Add tag...')}
|
||||
onChange={setNewTag}
|
||||
onKeyDown={onKeyDown}
|
||||
onSubmit={onSubmit}
|
||||
vocabulary={props.vocabulary || []} />
|
||||
}
|
||||
</div>
|
||||
|
|
|
@ -26,11 +26,6 @@ export default class RelationEditor extends Component {
|
|||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
content: getContent(props.relation)
|
||||
}
|
||||
|
||||
this.element = React.createRef();
|
||||
}
|
||||
|
||||
|
@ -42,11 +37,6 @@ export default class RelationEditor extends Component {
|
|||
this.setPosition();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(next) {
|
||||
if (this.props.relation !== next.relation)
|
||||
this.setState({ content : getContent(next.relation) });
|
||||
}
|
||||
|
||||
setPosition() {
|
||||
if (this.element.current) {
|
||||
const el = this.element.current;
|
||||
|
@ -57,32 +47,19 @@ export default class RelationEditor extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
onChange = value =>
|
||||
this.setState({ content: value });
|
||||
|
||||
onKeyDown = evt => {
|
||||
if (evt.which === 13) { // Enter = Submit
|
||||
evt.preventDefault();
|
||||
this.onSubmit();
|
||||
} else if (evt.which === 27) {
|
||||
this.props.onCancel();
|
||||
}
|
||||
}
|
||||
|
||||
onSubmit = () => {
|
||||
onSubmit = value => {
|
||||
const updatedAnnotation = this.props.relation.annotation.clone({
|
||||
motivation: 'linking',
|
||||
body: [{
|
||||
type: 'TextualBody',
|
||||
value: this.state.content,
|
||||
value,
|
||||
purpose: 'tagging'
|
||||
}]
|
||||
});
|
||||
|
||||
const updatedRelation = { ...this.props.relation, annotation: updatedAnnotation };
|
||||
|
||||
|
||||
if (this.state.content) {
|
||||
if (value) {
|
||||
// Fire create or update event
|
||||
if (this.props.relation.annotation.bodies.length === 0)
|
||||
this.props.onRelationCreated(updatedRelation, this.props.relation);
|
||||
|
@ -102,10 +79,10 @@ export default class RelationEditor extends Component {
|
|||
<div className="r6o-relation-editor" ref={this.element}>
|
||||
<div className="input-wrapper">
|
||||
<Autocomplete
|
||||
content={this.state.content}
|
||||
initialValue={getContent(this.props.relation)}
|
||||
placeholder="Tag..."
|
||||
onChange={this.onChange}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onSubmit={this.onSubmit}
|
||||
onCancel={this.props.onCancel}
|
||||
vocabulary={this.props.vocabulary || []} />
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Reference in New Issue