Introduces 'draft mode' tags, so user doesn't need to hit Enter to store
This commit is contained in:
parent
48d65ce520
commit
4373abf54b
|
@ -9,7 +9,6 @@ const Autocomplete = props => {
|
||||||
|
|
||||||
const onInputValueChange = ({ inputValue }) => {
|
const onInputValueChange = ({ inputValue }) => {
|
||||||
if (inputValue.length > 0) {
|
if (inputValue.length > 0) {
|
||||||
// Set suggestions to prefix matches...
|
|
||||||
const prefixMatches = props.vocabulary.filter(item => {
|
const prefixMatches = props.vocabulary.filter(item => {
|
||||||
return item.toLowerCase().startsWith(inputValue.toLowerCase());
|
return item.toLowerCase().startsWith(inputValue.toLowerCase());
|
||||||
});
|
});
|
||||||
|
@ -61,6 +60,7 @@ const Autocomplete = props => {
|
||||||
<div {...getComboboxProps()}>
|
<div {...getComboboxProps()}>
|
||||||
<input
|
<input
|
||||||
{...getInputProps({ onKeyDown })}
|
{...getInputProps({ onKeyDown })}
|
||||||
|
onChange={evt => props.onChange && props.onChange(evt)}
|
||||||
placeholder={props.placeholder}
|
placeholder={props.placeholder}
|
||||||
defaultValue={props.initialValue}
|
defaultValue={props.initialValue}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -5,14 +5,25 @@ import { CloseIcon } from '../../../Icons';
|
||||||
import i18n from '../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import Autocomplete from '../Autocomplete';
|
import Autocomplete from '../Autocomplete';
|
||||||
|
|
||||||
|
const getDraftTag = existingDraft =>
|
||||||
|
existingDraft ? existingDraft : {
|
||||||
|
type: 'TextualBody', value: '', purpose: 'tagging', draft: true
|
||||||
|
};
|
||||||
|
|
||||||
/** The basic freetext tag control from original Recogito **/
|
/** The basic freetext tag control from original Recogito **/
|
||||||
const TagWidget = props => {
|
const TagWidget = props => {
|
||||||
|
|
||||||
const [ showDelete, setShowDelete ] = useState(false);
|
// All tags (draft + non-draft)
|
||||||
|
const all = props.annotation ?
|
||||||
|
props.annotation.bodies.filter(b => b.type === 'TextualBody' && b.purpose === 'tagging') : [];
|
||||||
|
|
||||||
// Every body with a 'tagging' purpose is considered a tag
|
// Last draft tag goes into the input field
|
||||||
const tagBodies = props.annotation ?
|
const draftTag = getDraftTag(all.slice().reverse().find(b => b.draft));
|
||||||
props.annotation.bodies.filter(b => b.purpose === 'tagging') : [];
|
|
||||||
|
// All except draft tag
|
||||||
|
const tags = all.filter(b => b != draftTag);
|
||||||
|
|
||||||
|
const [ showDelete, setShowDelete ] = useState(false);
|
||||||
|
|
||||||
const toggle = tag => _ => {
|
const toggle = tag => _ => {
|
||||||
if (showDelete === tag) // Removes delete button
|
if (showDelete === tag) // Removes delete button
|
||||||
|
@ -26,16 +37,31 @@ const TagWidget = props => {
|
||||||
props.onRemoveBody(tag);
|
props.onRemoveBody(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onDraftChange = evt => {
|
||||||
|
const prev = draftTag.value.trim();
|
||||||
|
const updated = evt.target.value.trim();
|
||||||
|
|
||||||
|
if (prev.length === 0 && updated.length > 0) {
|
||||||
|
props.onAppendBody({ ...draftTag, value: updated });
|
||||||
|
} else if (prev.length > 0 && updated.length === 0) {
|
||||||
|
props.onRemoveBody(draftTag);
|
||||||
|
} else {
|
||||||
|
props.onUpdateBody(draftTag, { ...draftTag, value: updated });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const onSubmit = tag => {
|
const onSubmit = tag => {
|
||||||
props.onAppendBody({ type: 'TextualBody', purpose: 'tagging', value: tag.trim() });
|
// Just 'undraft' the current draft tag
|
||||||
|
const { draft, ...undrafted } = draftTag;
|
||||||
|
props.onUpdateBody(draftTag, undrafted);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="r6o-widget tag">
|
<div className="r6o-widget tag">
|
||||||
<div>
|
<div>
|
||||||
{ tagBodies.length > 0 &&
|
{ tags.length > 0 &&
|
||||||
<ul className="r6o-taglist">
|
<ul className="r6o-taglist">
|
||||||
{ tagBodies.map(tag =>
|
{ tags.map(tag =>
|
||||||
<li key={tag.value} onClick={toggle(tag.value)}>
|
<li key={tag.value} onClick={toggle(tag.value)}>
|
||||||
<span className="label">{tag.value}</span>
|
<span className="label">{tag.value}</span>
|
||||||
|
|
||||||
|
@ -54,9 +80,11 @@ const TagWidget = props => {
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ !props.readOnly &&
|
{!props.readOnly &&
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
placeholder={i18n.t('Add tag...')}
|
placeholder={i18n.t('Add tag...')}
|
||||||
|
initialValue={draftTag.value}
|
||||||
|
onChange={onDraftChange}
|
||||||
onSubmit={onSubmit}
|
onSubmit={onSubmit}
|
||||||
vocabulary={props.vocabulary || []} />
|
vocabulary={props.vocabulary || []} />
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue