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 Ajv from 'ajv'
|
||||
import isEqual from 'lodash/isEqual'
|
||||
import { updateIn, getIn, setIn } from '../utils/immutabilityHelpers'
|
||||
import { parseJSON } from '../utils/jsonUtils'
|
||||
import { enrichSchemaError } from '../utils/schemaUtils'
|
||||
import {
|
||||
jsonToData, dataToJson, toDataPath, patchData, pathExists,
|
||||
expand, addErrors, search, addSearchResults, addFocus
|
||||
expand, addErrors, search, addSearchResults, nextSearchResult, previousSearchResult
|
||||
} from '../jsonData'
|
||||
import {
|
||||
duplicate, insert, append, remove,
|
||||
|
@ -54,7 +55,7 @@ export default class TreeMode extends Component {
|
|||
|
||||
search: {
|
||||
text: '',
|
||||
selectedPath: null
|
||||
active: null // active search result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,14 +115,8 @@ export default class TreeMode extends Component {
|
|||
|
||||
// enrich the data with search results
|
||||
const searchResults = this.state.search.text ? search(data, this.state.search.text) : null
|
||||
if (searchResults && searchResults.length > 0) {
|
||||
const activeSearchResult = searchResults[0] // TODO: store active search result in state
|
||||
|
||||
data = addSearchResults(data, searchResults, activeSearchResult)
|
||||
|
||||
// TODO: highlight
|
||||
|
||||
// data = addFocus(data, searchResults[0]) // TODO: change to using focus from state
|
||||
if (searchResults) {
|
||||
data = addSearchResults(data, searchResults, this.state.search.active)
|
||||
}
|
||||
|
||||
// console.log('data', data)
|
||||
|
@ -316,19 +311,42 @@ export default class TreeMode extends Component {
|
|||
|
||||
/** @private */
|
||||
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 */
|
||||
handleNext = () => {
|
||||
// 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 */
|
||||
handlePrevious = () => {
|
||||
// TODO: implement select 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',
|
||||
className: 'jsoneditor-search-next',
|
||||
title: 'Next result',
|
||||
onClick: this.props.onPrevious
|
||||
onClick: this.props.onNext
|
||||
}),
|
||||
h('input', {
|
||||
key: 'previous',
|
||||
type: 'button',
|
||||
className: 'jsoneditor-search-previous',
|
||||
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 isEqual from 'lodash/isEqual'
|
||||
|
||||
import type {SearchResult} from './types'
|
||||
import type {JSONData, SearchResult} from './types'
|
||||
|
||||
/**
|
||||
* Expand function which will expand all nodes
|
||||
|
@ -508,12 +508,8 @@ export function addErrors (data, errors) {
|
|||
|
||||
/**
|
||||
* 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[] = []
|
||||
|
||||
traverse(data, function (value, path) {
|
||||
|
@ -593,25 +589,23 @@ export function previousSearchResult (searchResults: SearchResult[], current: Se
|
|||
/**
|
||||
* 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
|
||||
|
||||
if (searchResults) {
|
||||
searchResults.forEach(function (searchResult) {
|
||||
if (searchResult.type === 'value') {
|
||||
const dataPath = toDataPath(data, searchResult.dataPath).concat('searchResult')
|
||||
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
|
||||
updatedData = setIn(updatedData, dataPath, value)
|
||||
}
|
||||
searchResults.forEach(function (searchResult) {
|
||||
if (searchResult.type === 'value') {
|
||||
const dataPath = toDataPath(data, searchResult.dataPath).concat('searchResult')
|
||||
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
|
||||
updatedData = setIn(updatedData, dataPath, value)
|
||||
}
|
||||
|
||||
if (searchResult.type === 'property') {
|
||||
const valueDataPath = toDataPath(data, searchResult.dataPath)
|
||||
const propertyDataPath = allButLast(valueDataPath).concat('searchResult')
|
||||
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
|
||||
updatedData = setIn(updatedData, propertyDataPath, value)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (searchResult.type === 'property') {
|
||||
const valueDataPath = toDataPath(data, searchResult.dataPath)
|
||||
const propertyDataPath = allButLast(valueDataPath).concat('searchResult')
|
||||
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
|
||||
updatedData = setIn(updatedData, propertyDataPath, value)
|
||||
}
|
||||
})
|
||||
|
||||
return updatedData
|
||||
}
|
||||
|
@ -623,7 +617,7 @@ export function addSearchResults (data, searchResults: SearchResult[], activeSea
|
|||
* @param {SearchResult} focusOn
|
||||
* @return {JSONData} Returns an updated copy of data
|
||||
*/
|
||||
export function addFocus (data, focusOn) {
|
||||
export function addFocus (data: JSONData, focusOn: SearchResult) {
|
||||
if (focusOn.value) {
|
||||
const dataPath = toDataPath(data, focusOn.dataPath).concat('focusValue')
|
||||
return setIn(data, dataPath, true)
|
||||
|
|
Loading…
Reference in New Issue