Add bulk deletion to multi row context menu

This commit is contained in:
Andrew Kingston 2024-06-20 15:02:44 +01:00
parent 2dbf9a5118
commit f86c80af32
No known key found for this signature in database
4 changed files with 112 additions and 65 deletions

View File

@ -2,7 +2,8 @@
import { Modal, ModalContent } from "@budibase/bbui"
import { getContext, onMount } from "svelte"
const { selectedRows, rows, subscribe, notifications } = getContext("grid")
const { selectedRows, rows, subscribe, notifications, menu } =
getContext("grid")
let modal
@ -16,6 +17,9 @@
const count = rowsToDelete.length
await rows.actions.deleteRows(rowsToDelete)
$notifications.success(`Deleted ${count} row${count === 1 ? "" : "s"}`)
// Ensure menu is closed, as we may have triggered this from there
menu.actions.close()
}
onMount(() => subscribe("request-bulk-delete", () => modal?.show()))

View File

@ -20,6 +20,7 @@
focusedRowId,
notifications,
hasBudibaseIdentifiers,
selectedRowCount,
} = getContext("grid")
let anchor
@ -37,6 +38,10 @@
$notifications.success("Deleted 1 row")
}
const bulkDelete = () => {
dispatch("request-bulk-delete")
}
const duplicate = async () => {
menu.actions.close()
const newRow = await rows.actions.duplicateRow($focusedRow)
@ -58,59 +63,80 @@
{#key style}
<GridPopover {anchor} on:close={menu.actions.close} maxHeight={null}>
<Menu>
<MenuItem
icon="Copy"
on:click={clipboard.actions.copy}
on:click={menu.actions.close}
>
Copy
</MenuItem>
<MenuItem
icon="Paste"
disabled={$copiedCell == null || $focusedCellAPI?.isReadonly()}
on:click={clipboard.actions.paste}
on:click={menu.actions.close}
>
Paste
</MenuItem>
<MenuItem
icon="Maximize"
disabled={isNewRow || !$config.canEditRows || !$config.canExpandRows}
on:click={() => dispatch("edit-row", $focusedRow)}
on:click={menu.actions.close}
>
Edit row in modal
</MenuItem>
<MenuItem
icon="Copy"
disabled={isNewRow || !$focusedRow?._id || !$hasBudibaseIdentifiers}
on:click={() => copyToClipboard($focusedRow?._id)}
on:click={menu.actions.close}
>
Copy row _id
</MenuItem>
<MenuItem
icon="Copy"
disabled={isNewRow || !$focusedRow?._rev || !$hasBudibaseIdentifiers}
on:click={() => copyToClipboard($focusedRow?._rev)}
on:click={menu.actions.close}
>
Copy row _rev
</MenuItem>
<MenuItem
icon="Duplicate"
disabled={isNewRow || !$config.canAddRows}
on:click={duplicate}
>
Duplicate row
</MenuItem>
<MenuItem
icon="Delete"
disabled={isNewRow || !$config.canDeleteRows}
on:click={deleteRow}
>
Delete row
</MenuItem>
{#if $menu.multiRowMode}
<MenuItem
icon="Duplicate"
disabled={isNewRow || !$config.canAddRows}
on:click={duplicate}
>
Duplicate {$selectedRowCount} rows
</MenuItem>
<MenuItem
icon="Delete"
disabled={!$config.canDeleteRows}
on:click={bulkDelete}
>
Delete {$selectedRowCount} rows
</MenuItem>
{:else}
<MenuItem
icon="Copy"
on:click={clipboard.actions.copy}
on:click={menu.actions.close}
>
Copy
</MenuItem>
<MenuItem
icon="Paste"
disabled={$copiedCell == null || $focusedCellAPI?.isReadonly()}
on:click={clipboard.actions.paste}
on:click={menu.actions.close}
>
Paste
</MenuItem>
<MenuItem
icon="Maximize"
disabled={isNewRow ||
!$config.canEditRows ||
!$config.canExpandRows}
on:click={() => dispatch("edit-row", $focusedRow)}
on:click={menu.actions.close}
>
Edit row in modal
</MenuItem>
<MenuItem
icon="Copy"
disabled={isNewRow || !$focusedRow?._id || !$hasBudibaseIdentifiers}
on:click={() => copyToClipboard($focusedRow?._id)}
on:click={menu.actions.close}
>
Copy row _id
</MenuItem>
<MenuItem
icon="Copy"
disabled={isNewRow ||
!$focusedRow?._rev ||
!$hasBudibaseIdentifiers}
on:click={() => copyToClipboard($focusedRow?._rev)}
on:click={menu.actions.close}
>
Copy row _rev
</MenuItem>
<MenuItem
icon="Duplicate"
disabled={isNewRow || !$config.canAddRows}
on:click={duplicate}
>
Duplicate row
</MenuItem>
<MenuItem
icon="Delete"
disabled={isNewRow || !$config.canDeleteRows}
on:click={deleteRow}
>
Delete row
</MenuItem>
{/if}
</Menu>
</GridPopover>
{/key}

View File

@ -1,4 +1,5 @@
import { writable } from "svelte/store"
import { writable, get } from "svelte/store"
import { parseCellID } from "../lib/utils"
export const createStores = () => {
const menu = writable({
@ -13,7 +14,8 @@ export const createStores = () => {
}
export const createActions = context => {
const { menu, focusedCellId, gridID } = context
const { menu, focusedCellId, gridID, selectedRows, selectedRowCount } =
context
const open = (cellId, e) => {
e.preventDefault()
@ -29,11 +31,26 @@ export const createActions = context => {
// Compute bounds of cell relative to outer data node
const targetBounds = e.target.getBoundingClientRect()
const dataBounds = dataNode.getBoundingClientRect()
focusedCellId.set(cellId)
// Check if there are multiple rows selected, and this is one of them
let multiRowMode = false
if (get(selectedRowCount) > 1) {
const rowId = parseCellID(cellId).id
if (get(selectedRows)[rowId]) {
multiRowMode = true
}
}
// Only focus this cell if not in multi row mode
if (!multiRowMode) {
focusedCellId.set(cellId)
}
menu.set({
left: targetBounds.left - dataBounds.left + e.offsetX,
top: targetBounds.top - dataBounds.top + e.offsetY,
visible: true,
multiRowMode,
})
}

View File

@ -85,7 +85,7 @@ export const deriveStores = context => {
})
// Derive we have any selected rows or not
const hasSelectedRows = derived(selectedRows, $selectedRows => {
const selectedRowCount = derived(selectedRows, $selectedRows => {
return Object.keys($selectedRows).length
})
@ -94,7 +94,7 @@ export const deriveStores = context => {
focusedRow,
contentLines,
compact,
hasSelectedRows,
selectedRowCount,
}
}
@ -105,7 +105,7 @@ export const createActions = context => {
selectedRows,
rowLookupMap,
rows,
hasSelectedRows,
selectedRowCount,
} = context
// Keep the last selected index to use with bulk selection
let lastSelectedIndex = null
@ -133,7 +133,7 @@ export const createActions = context => {
}
const bulkSelectRows = id => {
if (!get(hasSelectedRows)) {
if (!get(selectedRowCount)) {
toggleSelectedRow(id)
return
}
@ -187,7 +187,7 @@ export const initialise = context => {
definition,
rowHeight,
fixedRowHeight,
hasSelectedRows,
selectedRowCount,
} = context
// Ensure we clear invalid rows from state if they disappear
@ -245,7 +245,7 @@ export const initialise = context => {
}
// Clear row selection when focusing a cell
if (id && get(hasSelectedRows)) {
if (id && get(selectedRowCount)) {
selectedRows.set({})
}
})
@ -267,8 +267,8 @@ export const initialise = context => {
})
// Clear focused cell when selecting rows
hasSelectedRows.subscribe(selected => {
if (get(focusedCellId) && selected) {
selectedRowCount.subscribe(count => {
if (get(focusedCellId) && count) {
focusedCellId.set(null)
}
})