Enhance Pinia History Plugin with State Filtering and Configuration Options

- Added an `ignoreKeys` option in the `mergeOptions` function of `pinia-history.js` to specify keys that should be excluded from history tracking, improving the plugin's flexibility.
- Introduced a new `filterState` function to filter out ignored keys from the state object, ensuring that only relevant state changes are tracked.
- Updated the history management logic to utilize the filtered state, enhancing the accuracy of undo/redo functionality.
- Modified the `working_form.js` store to include default ignored keys for history tracking, streamlining the configuration process.

These changes aim to improve the usability and performance of the Pinia history plugin by allowing developers to customize which state properties are tracked, thereby reducing unnecessary history entries.
This commit is contained in:
JhumanJ 2025-05-27 17:44:51 +02:00
parent f3a02df80e
commit 61fc30b95c
2 changed files with 38 additions and 8 deletions

View File

@ -25,7 +25,8 @@ function mergeOptions(options) {
} }
} }
}, },
debounceWait: 300 debounceWait: 300,
ignoreKeys: [] // Keys to ignore in history tracking
} }
return { return {
@ -34,6 +35,25 @@ function mergeOptions(options) {
} }
} }
/**
* Filters out ignored keys from the state object
* @param {Object} state - The state object to filter
* @param {Array} ignoreKeys - Array of keys to ignore
* @returns {Object} Filtered state object
*/
function filterState(state, ignoreKeys) {
if (!ignoreKeys || ignoreKeys.length === 0) {
return state
}
const filteredState = { ...state }
ignoreKeys.forEach(key => {
delete filteredState[key]
})
return filteredState
}
/** /**
* Adds undo/redo functionality to a Pinia store. * Adds undo/redo functionality to a Pinia store.
* @param {PiniaPluginContext} context - The context provided by Pinia. * @param {PiniaPluginContext} context - The context provided by Pinia.
@ -46,7 +66,7 @@ const PiniaHistory = (context) => {
return return
} }
const mergedOptions = mergeOptions(history) const mergedOptions = mergeOptions(history)
const {max, persistent, persistentStrategy} = mergedOptions const {max, persistent, persistentStrategy, ignoreKeys} = mergedOptions
const $history = reactive({ const $history = reactive({
max, max,
@ -54,19 +74,23 @@ const PiniaHistory = (context) => {
persistentStrategy, persistentStrategy,
done: [], done: [],
undone: [], undone: [],
current: JSON.stringify(store.$state), current: JSON.stringify(filterState(store.$state, ignoreKeys)),
trigger: true, trigger: true,
}) })
const debouncedStoreUpdate = debounce((state) => { const debouncedStoreUpdate = debounce((state) => {
if (hash($history.current) === hash(JSON.stringify(state))) { // Not a real change here const filteredState = filterState(state, ignoreKeys)
const currentStateHash = hash($history.current)
const newStateHash = hash(JSON.stringify(filteredState))
if (currentStateHash === newStateHash) { // Not a real change here
return return
} }
if ($history.done.length >= max) $history.done.shift() // Remove oldest state if needed if ($history.done.length >= max) $history.done.shift() // Remove oldest state if needed
$history.done.push($history.current) $history.done.push($history.current)
$history.undone = [] // Clear redo history on new action $history.undone = [] // Clear redo history on new action
$history.current = JSON.stringify(state) $history.current = JSON.stringify(filteredState)
if (persistent) { if (persistent) {
persistentStrategy.set(store, 'undo', $history.done) persistentStrategy.set(store, 'undo', $history.done)
@ -90,7 +114,9 @@ const PiniaHistory = (context) => {
$history.undone.push($history.current) // Save current state for redo $history.undone.push($history.current) // Save current state for redo
$history.trigger = false $history.trigger = false
store.$patch(JSON.parse(state)) // Only patch the state that was tracked (filtered state)
const stateToRestore = JSON.parse(state)
store.$patch(stateToRestore)
nextTick(() => { nextTick(() => {
$history.current = state $history.current = state
$history.trigger = true $history.trigger = true
@ -114,7 +140,9 @@ const PiniaHistory = (context) => {
$history.done.push($history.current) // Save current state for undo $history.done.push($history.current) // Save current state for undo
$history.trigger = false $history.trigger = false
store.$patch(JSON.parse(state)) // Only patch the state that was tracked (filtered state)
const stateToRestore = JSON.parse(state)
store.$patch(stateToRestore)
nextTick(() => { nextTick(() => {
$history.current = state $history.current = state
$history.trigger = true $history.trigger = true

View File

@ -253,5 +253,7 @@ export const useWorkingFormStore = defineStore("working_form", {
this.setProperties(newFields) this.setProperties(newFields)
} }
}, },
history: {} history: {
ignoreKeys: ['structureService', 'blockForm']
}
}) })