expand the active search result if not expanded

This commit is contained in:
jos 2017-01-01 21:13:14 +01:00
parent bef37648b7
commit 0e490fdeee
4 changed files with 56 additions and 23 deletions

View File

@ -1,13 +1,12 @@
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, addFocus,
expand, expandPath, addErrors,
search, addSearchResults, nextSearchResult, previousSearchResult
} from '../jsonData'
import {
@ -317,13 +316,14 @@ export default class TreeMode extends Component {
/** @private */
handleSearch = (text) => {
const searchResults = search(this.state.data, text)
const active = searchResults[0] || null
this.setState(setIn(this.state, ['search'], {
text,
active: searchResults[0] || null
}))
this.setState({
search: { text, active },
data: expandPath(this.state.data,active && active.path)
})
// TODO: focus on the active result
// TODO: scroll to the active result
}
/** @private */
@ -332,9 +332,12 @@ export default class TreeMode extends Component {
if (searchResults) {
const next = nextSearchResult(searchResults, this.state.search.active)
this.setState(setIn(this.state, ['search', 'active'], next))
this.setState({
search: setIn(this.state.search, ['active'], next),
data: expandPath(this.state.data, next && next.path)
})
// TODO: focus on the active result
// TODO: scroll to the active result
}
}
@ -344,9 +347,12 @@ export default class TreeMode extends Component {
if (searchResults) {
const previous = previousSearchResult(searchResults, this.state.search.active)
this.setState(setIn(this.state, ['search', 'active'], previous))
this.setState({
search: setIn(this.state.search, ['active'], previous),
data: expandPath(this.state.data, previous && previous.path)
})
// TODO: focus on the active result
// TODO: scroll to the active result
}
}

View File

@ -18,8 +18,7 @@ export default class Search extends Component {
}
render () {
// TODO: focus on search results
// TODO: expand the focused search result if not expanded
// TODO: scroll to active search result
return h('div', {className: 'jsoneditor-search'}, [
this.renderResultsCount(this.props.resultsCount),

View File

@ -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 {JSONData, DataPointer} from './types'
import type {JSONData, DataPointer, Path} from './types'
/**
* Expand function which will expand all nodes
@ -115,6 +115,17 @@ export function toDataPath (data, path) {
}
}
/**
* Convert a path of a JSON object into a path in the corresponding data model
* @param {JSONData} data
* @param {Path} path
* @return {Path} dataPath
* @private
*/
export function toPath (data, dataPath) {
}
/**
* Apply a patch to a JSONData object
* @param {JSONData} data
@ -458,10 +469,10 @@ export function test (data, path, value) {
* When a path, the object/array at this path will be expanded/collapsed
* When a function, all objects and arrays for which callback
* returns true will be expanded/collapsed
* @param {boolean} expanded New expanded state: true to expand, false to collapse
* @param {boolean} [expanded=true] New expanded state: true to expand, false to collapse
* @return {JSONData}
*/
export function expand (data, callback, expanded) {
export function expand (data, callback, expanded: boolean = true) {
// console.log('expand', callback, expand)
if (typeof callback === 'function') {
@ -485,6 +496,23 @@ export function expand (data, callback, expanded) {
}
}
/**
* Expand all Objects and Arrays on a path
*/
export function expandPath (data: JSONData, path: Path) {
let updatedData = data
if (path) {
for (let i = 0; i < path.length; i++) {
const pathPart = path.slice(0, i + 1)
// console.log('expandPath', path, i, pathPart)
updatedData = expand(updatedData, pathPart, true)
}
}
return updatedData
}
/**
* Merge one or multiple errors (for example JSON schema errors)
* into the data
@ -522,7 +550,7 @@ export function search (data: JSONData, text: string): DataPointer[] {
const parentPath = allButLast(path)
const parent = getIn(data, toDataPath(data, parentPath))
if (parent.type === 'Object') {
results.push({ dataPath: path, type: 'property' })
results.push({ path, type: 'property' })
}
}
}
@ -530,7 +558,7 @@ export function search (data: JSONData, text: string): DataPointer[] {
// check value
if (value.type === 'value') {
if (containsCaseInsensitive(value.value, text)) {
results.push({ dataPath: path, type: 'value' })
results.push({ path, type: 'value' })
}
}
})
@ -594,13 +622,13 @@ export function addSearchResults (data: JSONData, searchResults: DataPointer[],
searchResults.forEach(function (searchResult) {
if (searchResult.type === 'value') {
const dataPath = toDataPath(data, searchResult.dataPath).concat('searchResult')
const dataPath = toDataPath(data, searchResult.path).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 valueDataPath = toDataPath(data, searchResult.path)
const propertyDataPath = allButLast(valueDataPath).concat('searchResult')
const value = isEqual(searchResult, activeSearchResult) ? 'active' : 'normal'
updatedData = setIn(updatedData, propertyDataPath, value)
@ -615,12 +643,12 @@ export function addSearchResults (data: JSONData, searchResults: DataPointer[],
*/
export function addFocus (data: JSONData, focusOn: DataPointer) {
if (focusOn.type == 'value') {
const dataPath = toDataPath(data, focusOn.dataPath).concat('focus')
const dataPath = toDataPath(data, focusOn.path).concat('focus')
return setIn(data, dataPath, true)
}
if (focusOn.type === 'property') {
const valueDataPath = toDataPath(data, focusOn.dataPath)
const valueDataPath = toDataPath(data, focusOn.path)
const propertyDataPath = allButLast(valueDataPath).concat('focus')
return setIn(data, propertyDataPath, true)
}

View File

@ -83,7 +83,7 @@ export type JSONData = ObjectData | ArrayData | ValueData
export type Path = string[]
export type DataPointer = {
dataPath: Path,
path: Path,
type: DataPointerType
}
// TODO: DataPointer.dataPath is an array, JSONSchemaError.dataPath is a string -> make this consistent