Simplify and improve bulk pasting logic

This commit is contained in:
Andrew Kingston 2024-06-23 13:35:45 +01:00
parent 9c360a1f02
commit 70fd643431
No known key found for this signature in database
3 changed files with 76 additions and 44 deletions

View File

@ -95,9 +95,6 @@
selectedCells.actions.stopSelecting() selectedCells.actions.stopSelecting()
return return
} }
if ($focusedCellId) {
focusedCellId.set(null)
}
selectedCells.actions.updateTarget(cellId) selectedCells.actions.updateTarget(cellId)
} }
@ -109,7 +106,6 @@
if (e.shiftKey && $focusedCellId) { if (e.shiftKey && $focusedCellId) {
// If we have a focused cell, select the range from that cell to here // If we have a focused cell, select the range from that cell to here
selectedCells.actions.setRange($focusedCellId, cellId) selectedCells.actions.setRange($focusedCellId, cellId)
focusedCellId.set(null)
} else if (e.shiftKey && $selectedCellCount) { } else if (e.shiftKey && $selectedCellCount) {
// If we already have a selected range of cell, update it // If we already have a selected range of cell, update it
selectedCells.actions.updateTarget(cellId) selectedCells.actions.updateTarget(cellId)

View File

@ -1,6 +1,6 @@
import { derived, writable, get } from "svelte/store" import { derived, writable, get } from "svelte/store"
import { Helpers } from "@budibase/bbui" import { Helpers } from "@budibase/bbui"
import { parseCellID } from "../lib/utils" import { parseCellID, getCellID } from "../lib/utils"
export const createStores = () => { export const createStores = () => {
const clipboard = writable({ const clipboard = writable({
@ -62,6 +62,9 @@ export const createActions = context => {
rowLookupMap, rowLookupMap,
rowChangeCache, rowChangeCache,
rows, rows,
focusedCellId,
columnLookupMap,
allVisibleColumns,
} = context } = context
// Copies the currently selected value (or values) // Copies the currently selected value (or values)
@ -125,15 +128,67 @@ export const createActions = context => {
return return
} }
const { value, multiCellCopy } = get(clipboard) const { value, multiCellCopy } = get(clipboard)
const $focusedCellAPI = get(focusedCellAPI) const multiCellPaste = get(selectedCellCount) > 1
const $selectedCells = get(selectedCells)
const $selectedCellCount = get(selectedCellCount)
const multiCellPaste = $selectedCellCount > 1
// Choose paste strategy // Choose paste strategy
if (multiCellCopy) { if (multiCellCopy) {
if (multiCellPaste) { if (multiCellPaste) {
// Multi to multi (only paste selected cells) // Multi to multi (only paste selected cells)
await pasteIntoSelectedCells(value)
} else {
// Multi to single (expand to paste all values)
// Get indices of focused cell
const $focusedCellId = get(focusedCellId)
const { id, field } = parseCellID($focusedCellId)
const $rowLookupMap = get(rowLookupMap)
const $columnLookupMap = get(columnLookupMap)
const rowIdx = $rowLookupMap[id]
const colIdx = $columnLookupMap[field]
// Get limits of how many rows and columns we're able to paste into
const $rows = get(rows)
const $allVisibleColumns = get(allVisibleColumns)
const colCount = $allVisibleColumns.length
const rowCount = $rows.length
const selectedRows = value.length
const selectedColumns = value[0].length
const rowExtent = Math.min(selectedRows, rowCount - rowIdx) - 1
const colExtent = Math.min(selectedColumns, colCount - colIdx) - 1
// Get the target cell ID (bottom right of our pastable extent)
const targetRowId = $rows[rowIdx + rowExtent]._id
const targetColName = $allVisibleColumns[colIdx + colExtent].name
const targetCellId = getCellID(targetRowId, targetColName)
// Paste into target cell range
if (targetCellId === $focusedCellId) {
// Single cell edge case
get(focusedCellAPI).setValue(value[0][0])
} else {
// Select the new cells to paste into, then paste
selectedCells.actions.updateTarget(targetCellId)
await pasteIntoSelectedCells(value)
}
}
} else {
if (multiCellPaste) {
// Single to multi (duplicate value in all selected cells)
const $selectedCells = get(selectedCells)
const pastableValue = $selectedCells.map(row => {
return row.map(() => value)
})
await pasteIntoSelectedCells(pastableValue)
} else {
// Single to single
get(focusedCellAPI).setValue(value)
}
}
}
// Paste the specified value into the currently selected cells
const pasteIntoSelectedCells = async value => {
const $selectedCells = get(selectedCells)
// Find the extent at which we can paste // Find the extent at which we can paste
const rowExtent = Math.min(value.length, $selectedCells.length) const rowExtent = Math.min(value.length, $selectedCells.length)
const colExtent = Math.min(value[0].length, $selectedCells[0].length) const colExtent = Math.min(value[0].length, $selectedCells[0].length)
@ -151,29 +206,6 @@ export const createActions = context => {
} }
} }
await rows.actions.bulkUpdate(changeMap) await rows.actions.bulkUpdate(changeMap)
} else {
// Multi to single (expand to paste all values)
// TODO
}
} else {
if (multiCellPaste) {
// Single to multi (duplicate value in all selected cells)
let changeMap = {}
for (let row of $selectedCells) {
for (let cellId of row) {
const { id, field } = parseCellID(cellId)
if (!changeMap[id]) {
changeMap[id] = {}
}
changeMap[id][field] = value
}
}
await rows.actions.bulkUpdate(changeMap)
} else {
// Single to single
$focusedCellAPI.setValue(value)
}
}
} }
return { return {

View File

@ -217,9 +217,8 @@ export const createActions = context => {
toggleSelectedRow(id) toggleSelectedRow(id)
return return
} }
// There should always be a last selected index
if (lastSelectedIndex == null) { if (lastSelectedIndex == null) {
throw "NO LAST SELECTED INDEX" return
} }
const thisIndex = get(rowLookupMap)[id] const thisIndex = get(rowLookupMap)[id]
@ -417,10 +416,15 @@ export const initialise = context => {
} }
}) })
// Clear selected rows when selecting cells // Clear state when selecting cells
selectedCellCount.subscribe($selectedCellCount => { selectedCellCount.subscribe($selectedCellCount => {
if ($selectedCellCount && get(selectedRowCount)) { if ($selectedCellCount) {
if (get(selectedRowCount)) {
selectedRows.set({}) selectedRows.set({})
} }
if (get(focusedCellId)) {
focusedCellId.set(null)
}
}
}) })
} }