X-Git-Url: https://git.arvados.org/arvados-workbench2.git/blobdiff_plain/9a37cc202448e431064b247d36ac0229a6bfa9b2..e42867f560b3c2f4c09cf6a2c07c964c63714141:/src/views-components/resource-properties-form/property-key-field.tsx diff --git a/src/views-components/resource-properties-form/property-key-field.tsx b/src/views-components/resource-properties-form/property-key-field.tsx index 3fb2d377..0be4527a 100644 --- a/src/views-components/resource-properties-form/property-key-field.tsx +++ b/src/views-components/resource-properties-form/property-key-field.tsx @@ -2,45 +2,101 @@ // // SPDX-License-Identifier: AGPL-3.0 -import * as React from 'react'; -import { WrappedFieldProps, Field } from 'redux-form'; +import React from 'react'; +import { WrappedFieldProps, Field, FormName, reset, change, WrappedFieldInputProps, WrappedFieldMetaProps } from 'redux-form'; import { memoize } from 'lodash'; -import { Autocomplete } from '~/components/autocomplete/autocomplete'; -import { Vocabulary } from '~/models/vocabulary'; -import { connectVocabulary, VocabularyProp, buildProps } from '~/views-components/resource-properties-form/property-field-common'; -import { TAG_KEY_VALIDATION } from '~/validators/validators'; +import { Autocomplete } from 'components/autocomplete/autocomplete'; +import { + Vocabulary, + getTags, + getTagKeyID, + getTagKeyLabel, + getPreferredTags, + PropFieldSuggestion +} from 'models/vocabulary'; +import { + handleSelect, + handleBlur, + connectVocabulary, + VocabularyProp, + ValidationProp, + buildProps +} from 'views-components/resource-properties-form/property-field-common'; +import { TAG_KEY_VALIDATION } from 'validators/validators'; +import { escapeRegExp } from 'common/regexp'; +import { ChangeEvent } from 'react'; export const PROPERTY_KEY_FIELD_NAME = 'key'; +export const PROPERTY_KEY_FIELD_ID = 'keyID'; export const PropertyKeyField = connectVocabulary( - ({ vocabulary }: VocabularyProp) => + ({ vocabulary, skipValidation }: VocabularyProp & ValidationProp) => + ); + validate={skipValidation ? undefined : getValidation(vocabulary)} /> + +); -export const PropertyKeyInput = ({ vocabulary, ...props }: WrappedFieldProps & VocabularyProp) => - ; +const PropertyKeyInput = ({ vocabulary, ...props }: WrappedFieldProps & VocabularyProp) => + ( + s.synonyms && s.synonyms.length > 0 + ? `${s.label} (${s.synonyms.join('; ')})` + : s.label + } + onSelect={handleSelect(PROPERTY_KEY_FIELD_ID, data.form, props.input, props.meta)} + onBlur={() => { + // Case-insensitive search for the key in the vocabulary + const foundKeyID = getTagKeyID(props.input.value, vocabulary); + if (foundKeyID !== '') { + props.input.value = getTagKeyLabel(foundKeyID, vocabulary); + } + handleBlur(PROPERTY_KEY_FIELD_ID, data.form, props.meta, props.input, foundKeyID)(); + }} + onChange={(e: ChangeEvent) => { + const newValue = e.currentTarget.value; + handleChange(data.form, props.input, props.meta, newValue); + }} + /> + )} />; const getValidation = memoize( (vocabulary: Vocabulary) => - vocabulary.strict + vocabulary.strict_tags ? [...TAG_KEY_VALIDATION, matchTags(vocabulary)] : TAG_KEY_VALIDATION); const matchTags = (vocabulary: Vocabulary) => (value: string) => - getTagsList(vocabulary).find(tag => tag.includes(value)) + getTags(vocabulary).find(tag => tag.label === value) ? undefined : 'Incorrect key'; -const getSuggestions = (value: string, vocabulary: Vocabulary) => - getTagsList(vocabulary).filter(tag => tag.includes(value) && tag !== value); +const getSuggestions = (value: string, vocabulary: Vocabulary): PropFieldSuggestion[] => { + const re = new RegExp(escapeRegExp(value), "i"); + return getPreferredTags(vocabulary, value).filter( + tag => (tag.label !== value && re.test(tag.label)) || + (tag.synonyms && tag.synonyms.some(s => re.test(s)))); +}; -const getTagsList = ({ tags }: Vocabulary) => - Object.keys(tags); +const handleChange = ( + formName: string, + { onChange }: WrappedFieldInputProps, + { dispatch }: WrappedFieldMetaProps, + value: string) => { + // Properties' values are dependant on the keys, if any value is + // pre-existant, a change on the property key should mean that the + // previous value is invalid, so we better reset the whole form before + // setting the new tag key. + dispatch(reset(formName)); + + onChange(value); + dispatch(change(formName, PROPERTY_KEY_FIELD_NAME, value)); + }; \ No newline at end of file