1
0
Fork 0
mirror of synced 2024-07-06 15:00:49 +12:00

Refactor grid row actions to be more explicit and remove extraneous flags

This commit is contained in:
Andrew Kingston 2024-02-29 10:30:38 +00:00
parent e876d14b92
commit acecea5704
3 changed files with 54 additions and 54 deletions

View file

@ -59,13 +59,13 @@
isReadonly: () => readonly, isReadonly: () => readonly,
getType: () => column.schema.type, getType: () => column.schema.type,
getValue: () => row[column.name], getValue: () => row[column.name],
setValue: (value, options = { save: true }) => { setValue: (value, options = { apply: true }) => {
validation.actions.setError(cellId, null) validation.actions.setError(cellId, null)
updateValue({ updateValue({
rowId: row._id, rowId: row._id,
column: column.name, column: column.name,
value, value,
save: options?.save, apply: options?.apply,
}) })
}, },
} }

View file

@ -217,14 +217,14 @@
const type = $focusedCellAPI.getType() const type = $focusedCellAPI.getType()
if (type === "number" && keyCodeIsNumber(keyCode)) { if (type === "number" && keyCodeIsNumber(keyCode)) {
// Update the value locally but don't save it yet // Update the value locally but don't save it yet
$focusedCellAPI.setValue(parseInt(key), { save: false }) $focusedCellAPI.setValue(parseInt(key), { apply: false })
$focusedCellAPI.focus() $focusedCellAPI.focus()
} else if ( } else if (
["string", "barcodeqr", "longform"].includes(type) && ["string", "barcodeqr", "longform"].includes(type) &&
(keyCodeIsLetter(keyCode) || keyCodeIsNumber(keyCode)) (keyCodeIsLetter(keyCode) || keyCodeIsNumber(keyCode))
) { ) {
// Update the value locally but don't save it yet // Update the value locally but don't save it yet
$focusedCellAPI.setValue(key, { save: false }) $focusedCellAPI.setValue(key, { apply: false })
$focusedCellAPI.focus() $focusedCellAPI.focus()
} }
} }

View file

@ -3,6 +3,7 @@ import { fetchData } from "../../../fetch"
import { NewRowID, RowPageSize } from "../lib/constants" import { NewRowID, RowPageSize } from "../lib/constants"
import { tick } from "svelte" import { tick } from "svelte"
import { Helpers } from "@budibase/bbui" import { Helpers } from "@budibase/bbui"
import { isValid } from "@budibase/string-templates"
export const createStores = () => { export const createStores = () => {
const rows = writable([]) const rows = writable([])
@ -327,38 +328,31 @@ export const createActions = context => {
get(fetch)?.getInitialData() get(fetch)?.getInitialData()
} }
// Patches a row with some changes // Checks if a changeset for a row actually mutates the row or not
const updateRow = async ( const changesAreValid = (row, changes) => {
rowId, const columns = Object.keys(changes || {})
changes, if (!row || !columns.length) {
options = { save: true, force: false } return false
) => { }
// Ensure there is at least 1 column that creates a difference
return columns.some(column => row[column] !== changes[column])
}
// Patches a row with some changes in local state, and returns whether a
// valid pending change was made or not
const stashRowChanges = (rowId, changes) => {
const $rows = get(rows) const $rows = get(rows)
const $rowLookupMap = get(rowLookupMap) const $rowLookupMap = get(rowLookupMap)
const index = $rowLookupMap[rowId] const index = $rowLookupMap[rowId]
const row = $rows[index] const row = $rows[index]
if (index == null) {
return // Check this is a valid change
} if (!row || !changesAreValid(row, changes)) {
if (!options?.force && !Object.keys(changes || {}).length) { return false
return
} }
// Abandon if no changes // Add change to cache
if (!options?.force) {
let same = true
for (let column of Object.keys(changes)) {
if (row[column] !== changes[column]) {
same = false
break
}
}
if (same) {
return
}
}
// Immediately update state so that the change is reflected
rowChangeCache.update(state => ({ rowChangeCache.update(state => ({
...state, ...state,
[rowId]: { [rowId]: {
@ -366,26 +360,30 @@ export const createActions = context => {
...changes, ...changes,
}, },
})) }))
return true
}
// Stop here if we don't want to persist the change // Saves any pending changes to a row
if (!options?.save && !options?.force) { const applyRowChanges = async rowId => {
const $rows = get(rows)
const $rowLookupMap = get(rowLookupMap)
const index = $rowLookupMap[rowId]
const row = $rows[index]
if (row == null) {
return return
} }
// Save change // Save change
try { try {
inProgressChanges.update(state => ({ // Mark as in progress
...state, inProgressChanges.update(state => ({ ...state, [rowId]: true }))
[rowId]: true,
}))
// Update row // Update row
const saved = await datasource.actions.updateRow({ const changes = get(rowChangeCache)[rowId]
...cleanRow(row), const newRow = { ...cleanRow(row), ...changes }
...get(rowChangeCache)[rowId], const saved = await datasource.actions.updateRow(newRow)
})
// Update state after a successful change // Update row state after a successful change
if (saved?._id) { if (saved?._id) {
rows.update(state => { rows.update(state => {
state[index] = saved state[index] = saved
@ -395,6 +393,8 @@ export const createActions = context => {
// Handle users table edge case // Handle users table edge case
await refreshRow(saved.id) await refreshRow(saved.id)
} }
// Wipe row change cache now that we've saved the row
rowChangeCache.update(state => { rowChangeCache.update(state => {
delete state[rowId] delete state[rowId]
return state return state
@ -402,15 +402,17 @@ export const createActions = context => {
} catch (error) { } catch (error) {
handleValidationError(rowId, error) handleValidationError(rowId, error)
} }
inProgressChanges.update(state => ({
...state, // Mark as completed
[rowId]: false, inProgressChanges.update(state => ({ ...state, [rowId]: false }))
}))
} }
// Updates a value of a row // Updates a value of a row
const updateValue = async ({ rowId, column, value, save = true }) => { const updateValue = async ({ rowId, column, value, apply = true }) => {
return await updateRow(rowId, { [column]: value }, { save }) const success = stashRowChanges(rowId, { [column]: value })
if (success && apply) {
await applyRowChanges(rowId)
}
} }
// Deletes an array of rows // Deletes an array of rows
@ -420,9 +422,7 @@ export const createActions = context => {
} }
// Actually delete rows // Actually delete rows
rowsToDelete.forEach(row => { rowsToDelete.forEach(row => delete row.__idx)
delete row.__idx
})
await datasource.actions.deleteRows(rowsToDelete) await datasource.actions.deleteRows(rowsToDelete)
// Update state // Update state
@ -442,7 +442,7 @@ export const createActions = context => {
newRow = newRows[i] newRow = newRows[i]
// Ensure we have a unique _id. // Ensure we have a unique _id.
// This means generating one for non DS+, overriting any that may already // This means generating one for non DS+, overwriting any that may already
// exist as we cannot allow duplicates. // exist as we cannot allow duplicates.
if (!$isDatasourcePlus) { if (!$isDatasourcePlus) {
newRow._id = Helpers.uuid() newRow._id = Helpers.uuid()
@ -503,7 +503,7 @@ export const createActions = context => {
duplicateRow, duplicateRow,
getRow, getRow,
updateValue, updateValue,
updateRow, applyRowChanges,
deleteRows, deleteRows,
hasRow, hasRow,
loadNextPage, loadNextPage,
@ -537,13 +537,13 @@ export const initialise = context => {
}) })
// Ensure any unsaved changes are saved when changing cell // Ensure any unsaved changes are saved when changing cell
previousFocusedCellId.subscribe(id => { previousFocusedCellId.subscribe(async id => {
const rowId = id?.split("-")[0] const rowId = id?.split("-")[0]
const hasErrors = validation.actions.rowHasErrors(rowId) const hasErrors = validation.actions.rowHasErrors(rowId)
const hasChanges = Object.keys(get(rowChangeCache)[rowId] || {}).length > 0 const hasChanges = Object.keys(get(rowChangeCache)[rowId] || {}).length > 0
const isSavingChanges = get(inProgressChanges)[rowId] const isSavingChanges = get(inProgressChanges)[rowId]
if (rowId && !hasErrors && hasChanges && !isSavingChanges) { if (rowId && !hasErrors && hasChanges && !isSavingChanges) {
rows.actions.updateRow(rowId, null, { force: true }) await rows.actions.applyRowChanges(rowId)
} }
}) })
} }