From 4373abf54b48ba22992db934afb58067e43c5472 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Tue, 15 Sep 2020 15:09:32 +0200 Subject: [PATCH] Introduces 'draft mode' tags, so user doesn't need to hit Enter to store --- src/editor/widgets/Autocomplete.js | 2 +- src/editor/widgets/tag/TagWidget.jsx | 44 +++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/editor/widgets/Autocomplete.js b/src/editor/widgets/Autocomplete.js index 030e7a0..8dbb549 100644 --- a/src/editor/widgets/Autocomplete.js +++ b/src/editor/widgets/Autocomplete.js @@ -9,7 +9,6 @@ const Autocomplete = props => { const onInputValueChange = ({ inputValue }) => { if (inputValue.length > 0) { - // Set suggestions to prefix matches... const prefixMatches = props.vocabulary.filter(item => { return item.toLowerCase().startsWith(inputValue.toLowerCase()); }); @@ -61,6 +60,7 @@ const Autocomplete = props => {
props.onChange && props.onChange(evt)} placeholder={props.placeholder} defaultValue={props.initialValue} /> diff --git a/src/editor/widgets/tag/TagWidget.jsx b/src/editor/widgets/tag/TagWidget.jsx index 90571d9..ed802f9 100644 --- a/src/editor/widgets/tag/TagWidget.jsx +++ b/src/editor/widgets/tag/TagWidget.jsx @@ -5,14 +5,25 @@ import { CloseIcon } from '../../../Icons'; import i18n from '../../../i18n'; import Autocomplete from '../Autocomplete'; +const getDraftTag = existingDraft => + existingDraft ? existingDraft : { + type: 'TextualBody', value: '', purpose: 'tagging', draft: true + }; + /** The basic freetext tag control from original Recogito **/ 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 - const tagBodies = props.annotation ? - props.annotation.bodies.filter(b => b.purpose === 'tagging') : []; + // Last draft tag goes into the input field + const draftTag = getDraftTag(all.slice().reverse().find(b => b.draft)); + + // All except draft tag + const tags = all.filter(b => b != draftTag); + + const [ showDelete, setShowDelete ] = useState(false); const toggle = tag => _ => { if (showDelete === tag) // Removes delete button @@ -26,16 +37,31 @@ const TagWidget = props => { 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 => { - props.onAppendBody({ type: 'TextualBody', purpose: 'tagging', value: tag.trim() }); + // Just 'undraft' the current draft tag + const { draft, ...undrafted } = draftTag; + props.onUpdateBody(draftTag, undrafted); } return (
- { tagBodies.length > 0 && + { tags.length > 0 &&
    - { tagBodies.map(tag => + { tags.map(tag =>
  • {tag.value} @@ -54,9 +80,11 @@ const TagWidget = props => { }
- { !props.readOnly && + {!props.readOnly && }