Update search results on patch/undo/redo

This commit is contained in:
jos 2018-10-03 12:32:48 +02:00
parent 7012de59d6
commit 21d8db13d0
6 changed files with 49 additions and 76 deletions

View File

@ -61,7 +61,7 @@ import {
immutableESONPatch, immutableESONPatch,
nextSearchResult, nextSearchResult,
previousSearchResult, previousSearchResult,
search, applySearch,
SELECTION, SELECTION,
syncEson syncEson
} from '../eson' } from '../eson'
@ -142,8 +142,8 @@ export default class TreeMode extends PureComponent {
options: {}, options: {},
showSearch: false, showSearch: false,
searchText: '',
searchResult: { searchResult: {
text: '',
matches: null, matches: null,
active: null // active search result active: null // active search result
}, },
@ -327,7 +327,7 @@ export default class TreeMode extends PureComponent {
key: 'search', key: 'search',
ref: 'search', ref: 'search',
text: this.state.searchResult.text, text: this.state.searchText,
resultCount: this.state.searchResult.matches resultCount: this.state.searchResult.matches
? this.state.searchResult.matches.length ? this.state.searchResult.matches.length
@ -736,12 +736,12 @@ export default class TreeMode extends PureComponent {
} }
} }
handleSearch = (text) => { handleSearch = (searchText) => {
// FIXME: also apply search when eson is changed const { eson, searchResult } = applySearch(this.state.eson, searchText)
const { eson, searchResult } = search(this.state.eson, text)
if (searchResult.matches.length > 0) { if (searchResult.matches.length > 0) {
this.setState({ this.setState({
eson: expandPath(eson, initial(searchResult.active.path)), eson: expandPath(eson, initial(searchResult.active.path)),
searchText,
searchResult searchResult
}) })
@ -751,6 +751,7 @@ export default class TreeMode extends PureComponent {
else { else {
this.setState({ this.setState({
eson: eson, eson: eson,
searchText,
searchResult searchResult
}) })
} }
@ -818,11 +819,13 @@ export default class TreeMode extends PureComponent {
} }
handleCloseSearch = () => { handleCloseSearch = () => {
const { eson, searchResult } = search(this.state.eson, '') const searchText = ''
const { eson, searchResult } = applySearch(this.state.eson, searchText)
this.setState({ this.setState({
showSearch: false, showSearch: false,
eson, eson,
searchText,
searchResult searchResult
}) })
} }
@ -997,30 +1000,6 @@ export default class TreeMode extends PureComponent {
} }
} }
/**
* Get selection from an JSONPointer
* @param {ESONPointer} pointer
* @return {Selection}
*/
selectionFromJSONPointer (pointer) {
// FIXME: does pointer have .area === 'after' ? if so adjust type defs
if (pointer.area === 'after') {
return {after: pointer.path}
}
else if (pointer.area === 'inside') {
return {inside: pointer.path}
}
else if (pointer.area === 'empty') {
return {empty: pointer.path}
}
else if (pointer.area === 'emptyBefore') {
return {emptyBefore: pointer.path}
}
else {
return {start: pointer.path, end: pointer.path}
}
}
/** /**
* Scroll the window vertically to the node with given path * Scroll the window vertically to the node with given path
* @param {Path} path * @param {Path} path
@ -1090,19 +1069,23 @@ export default class TreeMode extends PureComponent {
const historyIndex = this.state.historyIndex const historyIndex = this.state.historyIndex
const historyItem = history[historyIndex] const historyItem = history[historyIndex]
const jsonResult = immutableJSONPatch(this.state.json, historyItem.undo) const { json } = immutableJSONPatch(this.state.json, historyItem.undo)
const esonResult = immutableESONPatch(this.state.eson, historyItem.undo) const esonResult = immutableESONPatch(this.state.eson, historyItem.undo)
// FIXME: apply search const { eson, searchResult } = (this.state.searchText)
? applySearch(esonResult.json, this.state.searchText)
: { eson: esonResult.json, searchResult: null }
this.setState({ this.setState({
json: jsonResult.json, json,
eson: esonResult.json, eson,
searchResult,
selection: historyItem.selectionBefore, selection: historyItem.selectionBefore,
history, history,
historyIndex: historyIndex + 1 historyIndex: historyIndex + 1
}) })
this.emitOnChange(historyItem.undo, historyItem.redo, jsonResult.json) this.emitOnChange(historyItem.undo, historyItem.redo, json)
} }
} }
@ -1112,19 +1095,23 @@ export default class TreeMode extends PureComponent {
const historyIndex = this.state.historyIndex - 1 const historyIndex = this.state.historyIndex - 1
const historyItem = history[historyIndex] const historyItem = history[historyIndex]
const jsonResult = immutableJSONPatch(this.state.json, historyItem.redo) const { json } = immutableJSONPatch(this.state.json, historyItem.redo)
const esonResult = immutableESONPatch(this.state.eson, historyItem.redo) const esonResult = immutableESONPatch(this.state.eson, historyItem.redo)
// FIXME: apply search const { eson, searchResult } = (this.state.searchText)
? applySearch(esonResult.json, this.state.searchText)
: { eson: esonResult.json, searchResult: null }
this.setState({ this.setState({
json: jsonResult.json, json,
eson: esonResult.json, eson,
searchResult,
selection: historyItem.selectionAfter, selection: historyItem.selectionAfter,
history, history,
historyIndex historyIndex
}) })
this.emitOnChange(historyItem.redo, historyItem.undo, jsonResult.json) this.emitOnChange(historyItem.redo, historyItem.undo, json)
} }
} }
@ -1149,6 +1136,10 @@ export default class TreeMode extends PureComponent {
const jsonResult = immutableJSONPatch(this.state.json, operations) const jsonResult = immutableJSONPatch(this.state.json, operations)
const esonResult = immutableESONPatch(this.state.eson, operations) const esonResult = immutableESONPatch(this.state.eson, operations)
const { eson, searchResult } = (this.state.searchText)
? applySearch(esonResult.json, this.state.searchText)
: { eson: esonResult.json, searchResult: null }
if (this.props.history !== false) { if (this.props.history !== false) {
// update data and store history // update data and store history
const historyItem = { const historyItem = {
@ -1162,10 +1153,10 @@ export default class TreeMode extends PureComponent {
.concat(this.state.history.slice(this.state.historyIndex)) .concat(this.state.history.slice(this.state.historyIndex))
.slice(0, MAX_HISTORY_ITEMS) .slice(0, MAX_HISTORY_ITEMS)
// FIXME: apply search
this.setState({ this.setState({
json: jsonResult.json, json: jsonResult.json,
eson: esonResult.json, eson,
searchResult,
selection: selectionAfter, selection: selectionAfter,
history, history,
historyIndex: 0 historyIndex: 0
@ -1173,10 +1164,10 @@ export default class TreeMode extends PureComponent {
} }
else { else {
// update data and don't store history // update data and don't store history
// FIXME: apply search
this.setState({ this.setState({
json: jsonResult.json, json: jsonResult.json,
eson: esonResult.json, eson,
searchResult,
selection: selectionAfter selection: selectionAfter
}) })
} }

View File

@ -340,22 +340,6 @@ div.jsoneditor-node-container {
} }
} }
&.jsoneditor-hover {
> .jsoneditor-node > .jsoneditor-button-container,
> .jsoneditor-node > .jsoneditor-button-placeholder {
background-color: $hoverColor;
}
> .jsoneditor-list {
border-left-color: $hoverColor;
}
> .jsoneditor-delimiter-end {
//padding-left: $line-height + $input-padding + 2px;
border-left-color: $hoverColor;
}
}
div.jsoneditor-floating-menu { div.jsoneditor-floating-menu {
position: absolute; position: absolute;
bottom: 100%; bottom: 100%;

View File

@ -9,9 +9,7 @@ $theme-color: #3883fa;
$theme-color-light: lighten($theme-color, 5); $theme-color-light: lighten($theme-color, 5);
$floating-menu-background: #4d4d4d; $floating-menu-background: #4d4d4d;
$floating-menu-color: #fff; $floating-menu-color: #fff;
$selectedColor: #ffed99; $selectedColor: #d3d3d3;
$hoverColor: #d3d3d3;
$hoverAndSelectedColor: #ffdb80;
$warning-color: #FBB917; $warning-color: #FBB917;
$gray: #9d9d9d; $gray: #9d9d9d;
$gray-icon: $gray; $gray-icon: $gray;

View File

@ -208,12 +208,12 @@ export function cleanupMetaData(eson, symbol, ignorePaths = []) {
/** /**
* Search some text in all properties and values * Search some text in all properties and values
* @param {ESON} eson * @param {ESON} eson
* @param {String} text Search text * @param {string} searchText
* @return {SearchResult} Returns search result: * @return {{eson: ESON, searchText: string, searchResult: SearchResult}} Returns search result:
* An updated eson object containing the search results, * An updated eson object containing the search results,
* and an array with the paths of all matches * and an array with the paths of all matches
*/ */
export function search (eson, text) { export function applySearch (eson, searchText) {
let matches = [] let matches = []
// TODO: keep active result from previous search if any? // TODO: keep active result from previous search if any?
@ -224,7 +224,7 @@ export function search (eson, text) {
// check property name // check property name
const prop = last(path) const prop = last(path)
if (text !== '' && containsCaseInsensitive(prop, text) && if (searchText !== '' && containsCaseInsensitive(prop, searchText) &&
getIn(eson, initial(path))[TYPE] === 'object') { // parent must be an Object getIn(eson, initial(path))[TYPE] === 'object') { // parent must be an Object
matches.push({path, area: 'property'}) matches.push({path, area: 'property'})
updatedValue = setIn(updatedValue, [SEARCH_PROPERTY], 'normal') updatedValue = setIn(updatedValue, [SEARCH_PROPERTY], 'normal')
@ -234,7 +234,7 @@ export function search (eson, text) {
} }
// check value // check value
if (value[TYPE] === 'value' && text !== '' && containsCaseInsensitive(value[VALUE], text)) { if (value[TYPE] === 'value' && searchText !== '' && containsCaseInsensitive(value[VALUE], searchText)) {
matches.push({path, area: 'value'}) matches.push({path, area: 'value'})
updatedValue = setIn(updatedValue, [SEARCH_VALUE], 'normal') updatedValue = setIn(updatedValue, [SEARCH_VALUE], 'normal')
} }
@ -271,8 +271,8 @@ export function search (eson, text) {
return { return {
eson: updatedEson, eson: updatedEson,
searchText,
searchResult: { searchResult: {
text,
matches, matches,
active active
} }

View File

@ -9,7 +9,7 @@ import {
nextSearchResult, nextSearchResult,
pathsFromSelection, pathsFromSelection,
previousSearchResult, previousSearchResult,
search, SEARCH_PROPERTY, SEARCH_VALUE, applySearch, SEARCH_PROPERTY, SEARCH_VALUE,
SELECTED, SELECTED,
SELECTED_END, SELECTED_END,
SELECTED_FIRST, SELECTED_FIRST,
@ -223,7 +223,7 @@ test('search', () => {
"nill": null, "nill": null,
"bool": false "bool": false
}) })
const result = search(eson, 'L') const result = applySearch(eson, 'L')
const esonWithSearch = result.eson const esonWithSearch = result.eson
const matches = result.searchResult.matches const matches = result.searchResult.matches
const active = result.searchResult.active const active = result.searchResult.active
@ -254,7 +254,7 @@ test('search number', () => {
"2": "two", "2": "two",
"arr": ["a", "b", "c", "2"] "arr": ["a", "b", "c", "2"]
}) })
const result = search(eson, '2') const result = applySearch(eson, '2')
const matches = result.searchResult.matches const matches = result.searchResult.matches
// should not match an array index, only props and values // should not match an array index, only props and values
@ -273,7 +273,7 @@ test('nextSearchResult', () => {
"nill": null, "nill": null,
"bool": false "bool": false
}) })
const first = search(eson, 'A') const first = applySearch(eson, 'A')
expect(first.searchResult.matches).toEqual([ expect(first.searchResult.matches).toEqual([
{path: ['bool'], area: 'value'}, {path: ['bool'], area: 'value'},
@ -314,7 +314,7 @@ test('previousSearchResult', () => {
"nill": null, "nill": null,
"bool": false "bool": false
}) })
const init = search(eson, 'A') const init = applySearch(eson, 'A')
expect(init.searchResult.matches).toEqual([ expect(init.searchResult.matches).toEqual([
{path: ['bool'], area: 'value'}, {path: ['bool'], area: 'value'},

View File

@ -45,7 +45,7 @@
*/ */
/** /**
* @typedef {{matches: ESONPointer[], active: ESONPointer, text: String}} SearchResult * @typedef {{matches: ESONPointer[], active: ESONPointer}} SearchResult
*/ */
/** /**