Implement methods `expandAll`, `collapseAll`, and Ctrl+Click on expand button

This commit is contained in:
josdejong 2020-06-02 21:41:59 +02:00
parent 40accb3f39
commit 61d91c2f9c
3 changed files with 35 additions and 15 deletions

View File

@ -11,7 +11,12 @@
import { faSearch, faUndo, faRedo } from '@fortawesome/free-solid-svg-icons' import { faSearch, faUndo, faRedo } from '@fortawesome/free-solid-svg-icons'
import { createHistory } from './history.js' import { createHistory } from './history.js'
import Node from './JSONNode.svelte' import Node from './JSONNode.svelte'
import { existsIn, getIn, setIn } from './utils/immutabilityHelpers.js' import {
existsIn,
getIn,
setIn,
updateIn
} from './utils/immutabilityHelpers.js'
import { compileJSONPointer, parseJSONPointer } from './utils/jsonPointer.js' import { compileJSONPointer, parseJSONPointer } from './utils/jsonPointer.js'
import { keyComboFromEvent } from './utils/keyBindings.js' import { keyComboFromEvent } from './utils/keyBindings.js'
import { flattenSearch, search } from './utils/search.js' import { flattenSearch, search } from './utils/search.js'
@ -54,6 +59,14 @@
}) })
let historyState = history.getState() let historyState = history.getState()
export function expandAll () {
state = syncState(doc, state, [], () => true, true)
}
export function collapseAll () {
state = syncState(doc, state, [], () => false, true)
}
export function get() { export function get() {
return doc return doc
} }
@ -227,10 +240,16 @@
* Toggle expanded state of a node * Toggle expanded state of a node
* @param {Path} path * @param {Path} path
* @param {boolean} expanded * @param {boolean} expanded
* @param {boolean} [recursive=false]
*/ */
function handleExpand (path, expanded) { function handleExpand (path, expanded, recursive = false) {
console.log('handleExpand', path, expanded) if (recursive) {
state = setIn(state, path.concat(STATE_EXPANDED), expanded) state = updateIn(state, path, (childState) => {
return syncState(getIn(doc, path), childState, [], () => expanded, true)
})
} else {
state = setIn(state, path.concat(STATE_EXPANDED), expanded)
}
} }
/** /**

View File

@ -82,8 +82,9 @@
}) })
} }
function toggle () { function toggleExpand (event) {
onExpand(path, !expanded) const recursive = event.ctrlKey
onExpand(path, !expanded, recursive)
} }
function updateKey () { function updateKey () {
@ -182,7 +183,7 @@
<div class='json-node'> <div class='json-node'>
{#if type === 'array'} {#if type === 'array'}
<div class='header'> <div class='header'>
<button class='expand' on:click={toggle}> <button class='expand' on:click={toggleExpand}>
{#if expanded} {#if expanded}
<Icon data={faCaretDown} /> <Icon data={faCaretDown} />
{:else} {:else}
@ -235,7 +236,7 @@
{/if} {/if}
{:else if type === 'object'} {:else if type === 'object'}
<div class='header'> <div class='header'>
<button class='expand' on:click={toggle}> <button class='expand' on:click={toggleExpand}>
{#if expanded} {#if expanded}
<Icon data={faCaretDown} /> <Icon data={faCaretDown} />
{:else} {:else}

View File

@ -12,9 +12,10 @@ import { updateProps } from './updateProps.js'
* @param {JSON | undefined} state * @param {JSON | undefined} state
* @param {Path} path * @param {Path} path
* @param {function (path: Path) : boolean} expand * @param {function (path: Path) : boolean} expand
* @param {boolean} [forceRefresh=false] if true, force refreshing the expanded state
* @returns {JSON | undefined} * @returns {JSON | undefined}
*/ */
export function syncState (document, state = undefined, path, expand) { export function syncState (document, state = undefined, path, expand, forceRefresh = false) {
// TODO: this function can be made way more efficient if we pass prevState: // TODO: this function can be made way more efficient if we pass prevState:
// when immutable, we can simply be done already when the state === prevState // when immutable, we can simply be done already when the state === prevState
@ -22,7 +23,8 @@ export function syncState (document, state = undefined, path, expand) {
const updatedState = {} const updatedState = {}
updatedState[STATE_PROPS] = updateProps(document, state && state[STATE_PROPS]) updatedState[STATE_PROPS] = updateProps(document, state && state[STATE_PROPS])
updatedState[STATE_EXPANDED] = state
updatedState[STATE_EXPANDED] = (state && !forceRefresh)
? state[STATE_EXPANDED] ? state[STATE_EXPANDED]
: expand(path) : expand(path)
@ -31,7 +33,7 @@ export function syncState (document, state = undefined, path, expand) {
const childDocument = document[key] const childDocument = document[key]
if (isObjectOrArray(childDocument)) { if (isObjectOrArray(childDocument)) {
const childState = state && state[key] const childState = state && state[key]
updatedState[key] = syncState(childDocument, childState, path.concat(key), expand) updatedState[key] = syncState(childDocument, childState, path.concat(key), expand, forceRefresh)
} }
}) })
} }
@ -42,13 +44,11 @@ export function syncState (document, state = undefined, path, expand) {
if (Array.isArray(document)) { if (Array.isArray(document)) {
const updatedState = [] const updatedState = []
// TODO: can we make the state for array a regular object { limit: 100, items: [...] }?
updatedState[STATE_LIMIT] = state updatedState[STATE_LIMIT] = state
? state[STATE_LIMIT] ? state[STATE_LIMIT]
: DEFAULT_LIMIT : DEFAULT_LIMIT
updatedState[STATE_EXPANDED] = state updatedState[STATE_EXPANDED] = (state && !forceRefresh)
? state[STATE_EXPANDED] ? state[STATE_EXPANDED]
: expand(path) : expand(path)
@ -57,7 +57,7 @@ export function syncState (document, state = undefined, path, expand) {
const childDocument = document[i] const childDocument = document[i]
if (isObjectOrArray(childDocument)) { if (isObjectOrArray(childDocument)) {
const childState = state && state[i] const childState = state && state[i]
updatedState[i] = syncState(childDocument, childState, path.concat(i), expand) updatedState[i] = syncState(childDocument, childState, path.concat(i), expand, forceRefresh)
} }
} }
} }