Implemented highlighting prev/next search result
This commit is contained in:
parent
6ba53f7364
commit
fec1bb8f23
|
@ -1,12 +1,13 @@
|
||||||
import { createElement as h, Component } from 'react'
|
import { createElement as h, Component } from 'react'
|
||||||
|
|
||||||
import Ajv from 'ajv'
|
import Ajv from 'ajv'
|
||||||
|
import isEqual from 'lodash/isEqual'
|
||||||
import { updateIn, getIn, setIn } from '../utils/immutabilityHelpers'
|
import { updateIn, getIn, setIn } from '../utils/immutabilityHelpers'
|
||||||
import { parseJSON } from '../utils/jsonUtils'
|
import { parseJSON } from '../utils/jsonUtils'
|
||||||
import { enrichSchemaError } from '../utils/schemaUtils'
|
import { enrichSchemaError } from '../utils/schemaUtils'
|
||||||
import {
|
import {
|
||||||
jsonToData, dataToJson, toDataPath, patchData, pathExists,
|
jsonToData, dataToJson, toDataPath, patchData, pathExists,
|
||||||
expand, addErrors, search, addSearchResults, addFocus
|
expand, addErrors, search, addSearchResults, nextSearchResult, previousSearchResult
|
||||||
} from '../jsonData'
|
} from '../jsonData'
|
||||||
import {
|
import {
|
||||||
duplicate, insert, append, remove,
|
duplicate, insert, append, remove,
|
||||||
|
@ -54,7 +55,7 @@ export default class TreeMode extends Component {
|
||||||
|
|
||||||
search: {
|
search: {
|
||||||
text: '',
|
text: '',
|
||||||
selectedPath: null
|
active: null // active search result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,14 +115,8 @@ export default class TreeMode extends Component {
|
||||||
|
|
||||||
// enrich the data with search results
|
// enrich the data with search results
|
||||||
const searchResults = this.state.search.text ? search(data, this.state.search.text) : null
|
const searchResults = this.state.search.text ? search(data, this.state.search.text) : null
|
||||||
if (searchResults && searchResults.length > 0) {
|
if (searchResults) {
|
||||||
const activeSearchResult = searchResults[0] // TODO: store active search result in state
|
data = addSearchResults(data, searchResults, this.state.search.active)
|
||||||
|
|
||||||
data = addSearchResults(data, searchResults, activeSearchResult)
|
|
||||||
|
|
||||||
// TODO: highlight
|
|
||||||
|
|
||||||
// data = addFocus(data, searchResults[0]) // TODO: change to using focus from state
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// console.log('data', data)
|
// console.log('data', data)
|
||||||
|
@ -316,19 +311,42 @@ export default class TreeMode extends Component {
|
||||||
|
|
||||||
/** @private */
|
/** @private */
|
||||||
handleSearch = (text) => {
|
handleSearch = (text) => {
|
||||||
this.setState(setIn(this.state, ['search', 'text'], text))
|
const searchResults = search(this.state.data, text)
|
||||||
|
|
||||||
|
this.setState(setIn(this.state, ['search'], {
|
||||||
|
text,
|
||||||
|
active: searchResults[0] || null
|
||||||
|
}))
|
||||||
|
|
||||||
|
// TODO: focus on the active result
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @private */
|
/** @private */
|
||||||
handleNext = () => {
|
handleNext = () => {
|
||||||
// TODO: implement select next search result
|
// TODO: implement select next search result
|
||||||
console.log('next search result...')
|
const searchResults = search(this.state.data, this.state.search.text)
|
||||||
|
if (searchResults) {
|
||||||
|
const next = nextSearchResult(searchResults, this.state.search.active)
|
||||||
|
|
||||||
|
this.setState(setIn(this.state, ['search', 'active'], next))
|
||||||
|
|
||||||
|
// TODO: focus on the active result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @private */
|
/** @private */
|
||||||
handlePrevious = () => {
|
handlePrevious = () => {
|
||||||
// TODO: implement select previous search result
|
// TODO: implement select previous search result
|
||||||
console.log('previous search result...')
|
console.log('previous search result...')
|
||||||
|
|
||||||
|
const searchResults = search(this.state.data, this.state.search.text)
|
||||||
|
if (searchResults) {
|
||||||
|
const previous = previousSearchResult(searchResults, this.state.search.active)
|
||||||
|
|
||||||
|
this.setState(setIn(this.state, ['search', 'active'], previous))
|
||||||
|
|
||||||
|
// TODO: focus on the active result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -36,14 +36,14 @@ export default class Search extends Component {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
className: 'jsoneditor-search-next',
|
className: 'jsoneditor-search-next',
|
||||||
title: 'Next result',
|
title: 'Next result',
|
||||||
onClick: this.props.onPrevious
|
onClick: this.props.onNext
|
||||||
}),
|
}),
|
||||||
h('input', {
|
h('input', {
|
||||||
key: 'previous',
|
key: 'previous',
|
||||||
type: 'button',
|
type: 'button',
|
||||||
className: 'jsoneditor-search-previous',
|
className: 'jsoneditor-search-previous',
|
||||||
title: 'Previous result',
|
title: 'Previous result',
|
||||||
onClick: this.props.onNext
|
onClick: this.props.onPrevious
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { setIn, updateIn, getIn, deleteIn, insertAt } from './utils/immutability
|
||||||
import { isObject } from './utils/typeUtils'
|
import { isObject } from './utils/typeUtils'
|
||||||
import isEqual from 'lodash/isEqual'
|
import isEqual from 'lodash/isEqual'
|
||||||
|
|
||||||
import type {SearchResult} from './types'
|
import type {JSONData, SearchResult} from './types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expand function which will expand all nodes
|
* Expand function which will expand all nodes
|
||||||
|
@ -508,12 +508,8 @@ export function addErrors (data, errors) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search some text in all properties and values
|
* Search some text in all properties and values
|
||||||
*
|
|
||||||
* @param {JSONData} data
|
|
||||||
* @param {string} text
|
|
||||||
* @return {SearchResult[]} Returns a list with search results
|
|
||||||
*/
|
*/
|
||||||
export function search (data, text): SearchResult[] {
|
export function search (data: JSONData, text: string): SearchResult[] {
|
||||||
let results: SearchResult[] = []
|
let results: SearchResult[] = []
|
||||||
|
|
||||||
traverse(data, function (value, path) {
|
traverse(data, function (value, path) {
|
||||||
|
@ -593,25 +589,23 @@ export function previousSearchResult (searchResults: SearchResult[], current: Se
|
||||||
/**
|
/**
|
||||||
* Merge searchResults into the data
|
* Merge searchResults into the data
|
||||||
*/
|
*/
|
||||||
export function addSearchResults (data, searchResults: SearchResult[], activeSearchResult: SearchResult) {
|
export function addSearchResults (data: JSONData, searchResults: SearchResult[], activeSearchResult: SearchResult) {
|
||||||
let updatedData = data
|
let updatedData = data
|
||||||
|
|
||||||
if (searchResults) {
|
searchResults.forEach(function (searchResult) {
|
||||||
searchResults.forEach(function (searchResult) {
|
if (searchResult.type === 'value') {
|
||||||
if (searchResult.type === 'value') {
|
const dataPath = toDataPath(data, searchResult.dataPath).concat('searchResult')
|
||||||
const dataPath = toDataPath(data, searchResult.dataPath).concat('searchResult')
|
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
|
||||||
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
|
updatedData = setIn(updatedData, dataPath, value)
|
||||||
updatedData = setIn(updatedData, dataPath, value)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (searchResult.type === 'property') {
|
if (searchResult.type === 'property') {
|
||||||
const valueDataPath = toDataPath(data, searchResult.dataPath)
|
const valueDataPath = toDataPath(data, searchResult.dataPath)
|
||||||
const propertyDataPath = allButLast(valueDataPath).concat('searchResult')
|
const propertyDataPath = allButLast(valueDataPath).concat('searchResult')
|
||||||
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
|
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
|
||||||
updatedData = setIn(updatedData, propertyDataPath, value)
|
updatedData = setIn(updatedData, propertyDataPath, value)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
return updatedData
|
return updatedData
|
||||||
}
|
}
|
||||||
|
@ -623,7 +617,7 @@ export function addSearchResults (data, searchResults: SearchResult[], activeSea
|
||||||
* @param {SearchResult} focusOn
|
* @param {SearchResult} focusOn
|
||||||
* @return {JSONData} Returns an updated copy of data
|
* @return {JSONData} Returns an updated copy of data
|
||||||
*/
|
*/
|
||||||
export function addFocus (data, focusOn) {
|
export function addFocus (data: JSONData, focusOn: SearchResult) {
|
||||||
if (focusOn.value) {
|
if (focusOn.value) {
|
||||||
const dataPath = toDataPath(data, focusOn.dataPath).concat('focusValue')
|
const dataPath = toDataPath(data, focusOn.dataPath).concat('focusValue')
|
||||||
return setIn(data, dataPath, true)
|
return setIn(data, dataPath, true)
|
||||||
|
|
Loading…
Reference in New Issue