Implemented function search
This commit is contained in:
parent
96186b836a
commit
e5e61b71e3
|
@ -461,7 +461,7 @@ export function expand (data, callback, expanded) {
|
|||
// console.log('expand', callback, expand)
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
return transform (data, function (value, path, root) {
|
||||
return transform (data, function (value, path) {
|
||||
if (value.type === 'Array' || value.type === 'Object') {
|
||||
if (callback(path)) {
|
||||
return setIn(value, ['expanded'], expanded)
|
||||
|
@ -503,18 +503,51 @@ export function addErrors (data, errors) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Merge one or multiple errors (for example JSON schema errors)
|
||||
* into the data
|
||||
* Search some text in all properties and values
|
||||
*
|
||||
* @param {JSONData} data
|
||||
* @param {string} search
|
||||
* @param {string} text
|
||||
* @return {JSONData} Returns an updated `data` object containing the search results
|
||||
*/
|
||||
export function setSearch (data, search) {
|
||||
let updatedData = data
|
||||
export function search (data, text) {
|
||||
return transform(data, function (value) {
|
||||
// search in values
|
||||
if (value.type === 'value') {
|
||||
if (containsCaseInsensitive(value.value, text)) {
|
||||
return setIn(value, ['search'], true)
|
||||
}
|
||||
else {
|
||||
return deleteIn(value, ['search'])
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: traverse over the data, add a field search: 'field'|'value' to all matching fields/values
|
||||
// search object property names
|
||||
if (value.type === 'Object') {
|
||||
let updatedProps = value.props
|
||||
updatedProps.forEach((prop, index) => {
|
||||
if (containsCaseInsensitive(prop.name, text)) {
|
||||
updatedProps = setIn(updatedProps, [index, 'search'], true)
|
||||
}
|
||||
else {
|
||||
updatedProps = deleteIn(updatedProps, [index, 'search'])
|
||||
}
|
||||
})
|
||||
|
||||
return updatedData
|
||||
return setIn(value, ['props'], updatedProps)
|
||||
}
|
||||
|
||||
return value
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a case insensitive search for a search text in a text
|
||||
* @param {String} text
|
||||
* @param {String} search
|
||||
* @return {boolean} Returns true if `search` is found in `text`
|
||||
*/
|
||||
export function containsCaseInsensitive (text, search) {
|
||||
return String(text).toLowerCase().indexOf(search.toLowerCase()) !== -1
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -543,8 +576,8 @@ function recurseTransform (value, path, root, callback) {
|
|||
let updatedItems = updatedValue.items
|
||||
|
||||
updatedValue.items.forEach((item, index) => {
|
||||
updatedItems = setIn(updatedItems, [index],
|
||||
recurseTransform(item, path.concat(String(index)), root, callback))
|
||||
const updatedItem = recurseTransform(item, path.concat(String(index)), root, callback)
|
||||
updatedItems = setIn(updatedItems, [index], updatedItem)
|
||||
})
|
||||
|
||||
updatedValue = setIn(updatedValue, ['items'], updatedItems)
|
||||
|
@ -556,8 +589,8 @@ function recurseTransform (value, path, root, callback) {
|
|||
let updatedProps = updatedValue.props
|
||||
|
||||
updatedValue.props.forEach((prop, index) => {
|
||||
updatedProps = setIn(updatedProps, [index, 'value'],
|
||||
recurseTransform(prop.value, path.concat(prop.name), root, callback))
|
||||
const updatedItem = recurseTransform(prop.value, path.concat(prop.name), root, callback)
|
||||
updatedProps = setIn(updatedProps, [index, 'value'], updatedItem)
|
||||
})
|
||||
|
||||
updatedValue = setIn(updatedValue, ['props'], updatedProps)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import test from 'ava';
|
||||
import {
|
||||
jsonToData, dataToJson, patchData, pathExists, transform,
|
||||
jsonToData, dataToJson, patchData, pathExists, transform, search,
|
||||
parseJSONPointer, compileJSONPointer,
|
||||
expand, addErrors
|
||||
} from '../src/jsonData'
|
||||
|
@ -237,6 +237,194 @@ const JSON_DATA_EXAMPLE_COLLAPSED_2 = {
|
|||
]
|
||||
}
|
||||
|
||||
// after search for 'O' (case insensitive)
|
||||
const JSON_DATA_EXAMPLE_SEARCH_1 = {
|
||||
type: 'Object',
|
||||
expanded: true,
|
||||
props: [
|
||||
{
|
||||
name: 'obj',
|
||||
search: true,
|
||||
value: {
|
||||
type: 'Object',
|
||||
expanded: true,
|
||||
props: [
|
||||
{
|
||||
name: 'arr',
|
||||
value: {
|
||||
type: 'Array',
|
||||
expanded: true,
|
||||
items: [
|
||||
{
|
||||
type: 'value',
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
value: 2
|
||||
},
|
||||
{
|
||||
type: 'Object',
|
||||
expanded: true,
|
||||
props: [
|
||||
{
|
||||
name: 'a',
|
||||
value: {
|
||||
type: 'value',
|
||||
value: 3
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'b',
|
||||
value: {
|
||||
type: 'value',
|
||||
value: 4
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'str',
|
||||
value: {
|
||||
type: 'value',
|
||||
value: 'hello world',
|
||||
search: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'nill',
|
||||
value: {
|
||||
type: 'value',
|
||||
value: null
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'bool',
|
||||
search: true,
|
||||
value: {
|
||||
type: 'value',
|
||||
value: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// after search for '2'
|
||||
const JSON_DATA_EXAMPLE_SEARCH_2 = {
|
||||
type: 'Object',
|
||||
expanded: true,
|
||||
props: [
|
||||
{
|
||||
name: 'obj',
|
||||
value: {
|
||||
type: 'Object',
|
||||
expanded: true,
|
||||
props: [
|
||||
{
|
||||
name: 'arr',
|
||||
value: {
|
||||
type: 'Array',
|
||||
expanded: true,
|
||||
items: [
|
||||
{
|
||||
type: 'value',
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
value: 2,
|
||||
search: true
|
||||
},
|
||||
{
|
||||
type: 'Object',
|
||||
expanded: true,
|
||||
props: [
|
||||
{
|
||||
name: 'a',
|
||||
value: {
|
||||
type: 'value',
|
||||
value: 3
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'b',
|
||||
value: {
|
||||
type: 'value',
|
||||
value: 4
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'str',
|
||||
value: {
|
||||
type: 'value',
|
||||
value: 'hello world'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'nill',
|
||||
value: {
|
||||
type: 'value',
|
||||
value: null
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'bool',
|
||||
value: {
|
||||
type: 'value',
|
||||
value: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const JSON_DATA_SMALL = {
|
||||
type: 'Object',
|
||||
props: [
|
||||
{
|
||||
name: 'obj',
|
||||
value: {
|
||||
type: 'Object',
|
||||
props: [
|
||||
{
|
||||
name: 'a',
|
||||
value: {
|
||||
type: 'value',
|
||||
value: 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'arr',
|
||||
value: {
|
||||
type: 'Array',
|
||||
items: [
|
||||
{
|
||||
type: 'value',
|
||||
value: 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
const JSON_SCHEMA_ERRORS = [
|
||||
{dataPath: '/obj/arr/2/b', message: 'String expected'},
|
||||
{dataPath: '/nill', message: 'Null expected'}
|
||||
|
@ -740,43 +928,10 @@ test('add and remove errors', t => {
|
|||
|
||||
test('transform', t => {
|
||||
// {obj: {a: 2}, arr: [3]}
|
||||
const data = {
|
||||
type: 'Object',
|
||||
props: [
|
||||
{
|
||||
name: 'obj',
|
||||
value: {
|
||||
type: 'Object',
|
||||
props: [
|
||||
{
|
||||
name: 'a',
|
||||
value: {
|
||||
type: 'value',
|
||||
value: 2
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'arr',
|
||||
value: {
|
||||
type: 'Array',
|
||||
items: [
|
||||
{
|
||||
type: 'value',
|
||||
value: 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
let log = []
|
||||
const transformed = transform(data, function (value, path, root) {
|
||||
t.truthy(root === data)
|
||||
const transformed = transform(JSON_DATA_SMALL, function (value, path, root) {
|
||||
t.truthy(root === JSON_DATA_SMALL)
|
||||
|
||||
log.push([value, path, root])
|
||||
|
||||
|
@ -792,21 +947,31 @@ test('transform', t => {
|
|||
// console.log('transformed', JSON.stringify(transformed, null, 2))
|
||||
|
||||
const EXPECTED_LOG = [
|
||||
[data, [], data],
|
||||
[data.props[0].value, ['obj'], data],
|
||||
[data.props[0].value.props[0].value, ['obj', 'a'], data],
|
||||
[data.props[1].value, ['arr'], data],
|
||||
[data.props[1].value.items[0], ['arr', '0'], data],
|
||||
[JSON_DATA_SMALL, [], JSON_DATA_SMALL],
|
||||
[JSON_DATA_SMALL.props[0].value, ['obj'], JSON_DATA_SMALL],
|
||||
[JSON_DATA_SMALL.props[0].value.props[0].value, ['obj', 'a'], JSON_DATA_SMALL],
|
||||
[JSON_DATA_SMALL.props[1].value, ['arr'], JSON_DATA_SMALL],
|
||||
[JSON_DATA_SMALL.props[1].value.items[0], ['arr', '0'], JSON_DATA_SMALL],
|
||||
]
|
||||
|
||||
// log.forEach((row, index) => {
|
||||
// t.deepEqual(log[index], EXPECTED_LOG[index], 'should have equal log at index ' + index )
|
||||
// })
|
||||
t.deepEqual(log, EXPECTED_LOG)
|
||||
t.truthy(transformed !== data)
|
||||
t.truthy(transformed.props[0].value !== data.props[0].value)
|
||||
t.truthy(transformed.props[0].value.props[0].value !== data.props[0].value.props[0].value)
|
||||
t.truthy(data.props[1].value === data.props[1].value)
|
||||
t.truthy(data.props[1].value.items[0] === data.props[1].value.items[0])
|
||||
t.truthy(transformed !== JSON_DATA_SMALL)
|
||||
t.truthy(transformed.props[0].value !== JSON_DATA_SMALL.props[0].value)
|
||||
t.truthy(transformed.props[0].value.props[0].value !== JSON_DATA_SMALL.props[0].value.props[0].value)
|
||||
t.truthy(JSON_DATA_SMALL.props[1].value === JSON_DATA_SMALL.props[1].value)
|
||||
t.truthy(JSON_DATA_SMALL.props[1].value.items[0] === JSON_DATA_SMALL.props[1].value.items[0])
|
||||
|
||||
})
|
||||
|
||||
|
||||
test('search', t => {
|
||||
const result1 = search(JSON_DATA_EXAMPLE, 'O')
|
||||
t.deepEqual(result1, JSON_DATA_EXAMPLE_SEARCH_1)
|
||||
|
||||
// search for something else. Should clean up earlier search results
|
||||
const result2 = search(result1, '2')
|
||||
t.deepEqual(result2, JSON_DATA_EXAMPLE_SEARCH_2)
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue