-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow some special characters on TagsQuery component #205
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'contexture-util': patch | ||
--- | ||
|
||
New contexture-util package |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'contexture-elasticsearch': patch | ||
'contexture-react': patch | ||
--- | ||
|
||
Allow some special characters in TagsQuery component |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,17 @@ | ||
import React, { forwardRef } from 'react' | ||
import _ from 'lodash/fp.js' | ||
import { observable } from '../utils/mobx.js' | ||
import { observer, inject } from 'mobx-react' | ||
import { observer } from 'mobx-react' | ||
import Flex from './Flex.js' | ||
import DefaultTag from './Tag.js' | ||
import { sanitizeTagWords, splitTagOnComma, wordRegex } from './utils.js' | ||
import { createTags } from './utils.js' | ||
|
||
let isValidInput = (tag, tags) => !_.isEmpty(tag) && !_.includes(tag, tags) | ||
|
||
let TagsInput = forwardRef( | ||
( | ||
{ | ||
tags, | ||
addTags, | ||
addTags: setTags, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see setTags in the story but nowhere else, where is this used? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
removeTag, | ||
submit = _.noop, | ||
tagStyle, | ||
|
@@ -22,10 +21,7 @@ let TagsInput = forwardRef( | |
onBlur = _.noop, | ||
onInputChange = _.noop, | ||
onTagClick = _.noop, | ||
maxWordsPerTag = 100, | ||
maxCharsPerTagWord = 100, | ||
wordsMatchPattern = wordRegex, | ||
sanitizeTags = true, | ||
sanitizeTagFn, | ||
Tag = DefaultTag, | ||
...props | ||
}, | ||
|
@@ -34,19 +30,10 @@ let TagsInput = forwardRef( | |
let containerRef = React.useRef() | ||
let [currentInput, setCurrentInput] = React.useState('') | ||
|
||
let sanitizeTagFn = sanitizeTagWords( | ||
wordsMatchPattern, | ||
maxWordsPerTag, | ||
maxCharsPerTagWord | ||
) | ||
|
||
addTags = _.flow( | ||
_.trim, | ||
(tags) => (splitCommas ? splitTagOnComma(tags) : _.castArray(tags)), | ||
(tags) => (sanitizeTags ? _.map(sanitizeTagFn, tags) : tags), | ||
_.difference(_, tags), | ||
addTags | ||
) | ||
let addTags = (input) => { | ||
let newTags = createTags({ input, splitCommas, sanitizeTagFn }) | ||
setTags(_.difference(newTags, tags)) | ||
} | ||
|
||
return ( | ||
<div className={'tags-input'} ref={containerRef} style={{ ...style }}> | ||
|
@@ -118,19 +105,4 @@ let TagsInput = forwardRef( | |
} | ||
) | ||
|
||
// Just uses an internal observable array | ||
export let MockTagsInput = inject(() => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This component was unused. Looks like it was used for a test at some point. |
||
let tags = observable([]) | ||
return { | ||
tags, | ||
addTags(tag) { | ||
tags.push(tag) | ||
}, | ||
removeTag(tag) { | ||
tags = _.without(tag, tags) | ||
}, | ||
} | ||
})(TagsInput) | ||
MockTagsInput.displayName = 'MockTagsInput' | ||
|
||
export default observer(TagsInput) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import _ from 'lodash/fp.js' | ||
import React from 'react' | ||
import TagsInput from './TagsInput.js' | ||
|
||
export default { | ||
component: TagsInput, | ||
} | ||
|
||
export const Default = () => { | ||
let [tags, setTags] = React.useState([ | ||
'janitor', | ||
'soap', | ||
'cleaner', | ||
'cleaning', | ||
'clean', | ||
]) | ||
return ( | ||
<TagsInput | ||
tags={tags} | ||
addTags={(tags) => setTags((current) => _.union(tags, current))} | ||
removeTag={(tag) => setTags((current) => _.pull(tag, current))} | ||
tagStyle={{ background: 'lavender' }} | ||
/> | ||
) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,58 @@ | ||
import _ from 'lodash/fp.js' | ||
import F from 'futil' | ||
import { queryStringCharacterBlacklist } from 'contexture-util/exampleTypes/tagsQuery.js' | ||
import escapeStringRegexp from 'escape-string-regexp' | ||
|
||
export let openBinding = (...lens) => ({ | ||
isOpen: F.view(...lens), | ||
onClose: F.off(...lens), | ||
}) | ||
|
||
let maxWordsPerTag = 100 | ||
let maxCharsPerTagWord = 100 | ||
|
||
// Strip these characters when splitting a tag into words. We do this to display | ||
// tags that are closer to what we send to elastic in a `query_string` query. | ||
// | ||
// See https://github.com/smartprocure/contexture-elasticsearch/pull/170 | ||
// | ||
// If in doubt, make a request to the `/{index}/analyze` elasticsearch endpoint | ||
// to see exactly which characters get stripped out of text. | ||
let wordRegexp = new RegExp( | ||
`[^${escapeStringRegexp(queryStringCharacterBlacklist)}]+`, | ||
'g' | ||
) | ||
let words = _.words.convert({ fixed: false }) | ||
|
||
// Convert string to words, take the first maxWordsPerTag, truncate them and convert back to string | ||
export let sanitizeTagWords = ( | ||
wordsMatchPattern, | ||
maxWordsPerTag, | ||
maxCharsPerTagWord | ||
) => { | ||
let words = _.words.convert({ fixed: false }) | ||
return _.flow( | ||
(string) => words(string, wordsMatchPattern), | ||
_.take(maxWordsPerTag), | ||
_.map((word) => | ||
_.flow( | ||
_.truncate({ length: maxCharsPerTagWord, omission: '' }), | ||
// Remove beginning of line dash and space dash | ||
_.replace(/^-| -/g, ' '), | ||
_.trim | ||
)(word) | ||
), | ||
_.join(' ') | ||
) | ||
} | ||
export let sanitizeQueryStringTag = _.flow( | ||
(string) => words(string, wordRegexp), | ||
_.take(maxWordsPerTag), | ||
_.map((word) => | ||
_.flow( | ||
_.truncate({ length: maxCharsPerTagWord, omission: '' }), | ||
// Remove beginning of line dash and space dash | ||
// https://github.com/smartprocure/spark/issues/10923 | ||
_.replace(/^-| -/g, ' '), | ||
_.trim | ||
)(word) | ||
), | ||
_.join(' ') | ||
) | ||
|
||
// Split a tag on comma into unique words | ||
export let splitTagOnComma = _.flow( | ||
_.trim, | ||
let splitTagOnComma = _.flow( | ||
_.split(','), | ||
_.invokeMap('trim'), | ||
_.compact, | ||
_.uniq | ||
) | ||
|
||
export let wordRegex = /[-\w]+/g | ||
export let wordRegexWithDot = /[-.\w]+/g | ||
export let createTags = ({ input, splitCommas, sanitizeTagFn }) => | ||
_.flow( | ||
_.trim, | ||
splitCommas ? splitTagOnComma : _.identity, | ||
_.castArray, | ||
sanitizeTagFn ? _.map(sanitizeTagFn) : _.identity, | ||
_.compact | ||
)(input) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# common | ||
|
||
Utilities common to all packages. | ||
|
||
Code in this package should be isomorphic (e.g. should run on both node and the browser). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This dependency was duplicated.