diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index e9c8643bce..bbe116721a 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -491,6 +491,7 @@ const getSelectedRowsBindings = asset => { readableBinding: `${table._instanceName}.Selected rows`, category: "Selected rows", icon: "ViewRow", + display: { name: table._instanceName }, })) ) @@ -506,6 +507,7 @@ const getSelectedRowsBindings = asset => { )}.${makePropSafe("selectedRows")}`, readableBinding: `${block._instanceName}.Selected rows`, category: "Selected rows", + display: { name: block._instanceName }, })) ) } diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DeleteRow.svelte b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DeleteRow.svelte index 109eb9a956..e4a5f171ff 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DeleteRow.svelte +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/actions/DeleteRow.svelte @@ -1,5 +1,5 @@
- - Please specify one or more rows to delete. +
+ + + {/if} +
diff --git a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/manifest.json b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/manifest.json index 2ec7235c59..6ed545f541 100644 --- a/packages/builder/src/components/design/settings/controls/ButtonActionEditor/manifest.json +++ b/packages/builder/src/components/design/settings/controls/ButtonActionEditor/manifest.json @@ -24,6 +24,7 @@ }, { "name": "Delete Row", + "displayName": "Delete Rows", "type": "data", "component": "DeleteRow" }, diff --git a/packages/client/src/components/app/table/Table.svelte b/packages/client/src/components/app/table/Table.svelte index 248151a7a2..0ed76317db 100644 --- a/packages/client/src/components/app/table/Table.svelte +++ b/packages/client/src/components/app/table/Table.svelte @@ -47,6 +47,14 @@ ) } + // If the data changes, double check that the selected elements are still present. + $: if (data) { + let rowIds = data.map(row => row._id) + if (rowIds.length) { + selectedRows = selectedRows.filter(row => rowIds.includes(row._id)) + } + } + const getFields = (schema, customColumns, showAutoColumns) => { // Check for an invalid column selection let invalid = false diff --git a/packages/client/src/utils/buttonActions.js b/packages/client/src/utils/buttonActions.js index 68f312f0ad..97d0d827bd 100644 --- a/packages/client/src/utils/buttonActions.js +++ b/packages/client/src/utils/buttonActions.js @@ -101,13 +101,47 @@ const fetchRowHandler = async action => { } } -const deleteRowHandler = async action => { - const { tableId, revId, rowId, notificationOverride } = action.parameters - if (tableId && rowId) { +const deleteRowHandler = async (action, context) => { + const { tableId, rowId: rowConfig, notificationOverride } = action.parameters + + if (tableId && rowConfig) { try { - await API.deleteRow({ tableId, rowId, revId }) + let requestConfig + + let parsedRowConfig = [] + if (typeof rowConfig === "string") { + try { + parsedRowConfig = JSON.parse(rowConfig) + } catch (e) { + parsedRowConfig = rowConfig + .split(",") + .map(id => id.trim()) + .filter(id => id) + } + } else { + parsedRowConfig = rowConfig + } + + if ( + typeof parsedRowConfig === "object" && + parsedRowConfig.constructor === Object + ) { + requestConfig = [parsedRowConfig] + } else if (Array.isArray(parsedRowConfig)) { + requestConfig = parsedRowConfig + } + + if (!requestConfig.length) { + notificationStore.actions.warning("No valid rows were supplied") + return false + } + + const resp = await API.deleteRows({ tableId, rows: requestConfig }) + if (!notificationOverride) { - notificationStore.actions.success("Row deleted") + notificationStore.actions.success( + resp?.length == 1 ? "Row deleted" : `${resp.length} Rows deleted` + ) } // Refresh related datasources @@ -115,8 +149,10 @@ const deleteRowHandler = async action => { invalidateRelationships: true, }) } catch (error) { - // Abort next actions - return false + console.error(error) + notificationStore.actions.error( + "An error occurred while executing the query" + ) } } } diff --git a/packages/server/src/api/controllers/public/rows.ts b/packages/server/src/api/controllers/public/rows.ts index df856f1fe0..39cf85a2a3 100644 --- a/packages/server/src/api/controllers/public/rows.ts +++ b/packages/server/src/api/controllers/public/rows.ts @@ -5,7 +5,7 @@ import { convertBookmark } from "../../../utilities" // makes sure that the user doesn't need to pass in the type, tableId or _id params for // the call to be correct -function fixRow(row: Row, params: any) { +export function fixRow(row: Row, params: any) { if (!params || !row) { return row } diff --git a/packages/server/src/api/controllers/row/index.ts b/packages/server/src/api/controllers/row/index.ts index 91270429a4..6a969affaf 100644 --- a/packages/server/src/api/controllers/row/index.ts +++ b/packages/server/src/api/controllers/row/index.ts @@ -5,6 +5,8 @@ import { isExternalTable } from "../../../integrations/utils" import { Ctx } from "@budibase/types" import * as utils from "./utils" import { gridSocket } from "../../../websockets" +import { addRev } from "../public/utils" +import { fixRow } from "../public/rows" function pickApi(tableId: any) { if (isExternalTable(tableId)) { @@ -88,7 +90,22 @@ export async function destroy(ctx: any) { const inputs = ctx.request.body const tableId = utils.getTableId(ctx) let response, row + if (inputs.rows) { + const targetRows = inputs.rows.map( + (row: { [key: string]: string | string }) => { + let processedRow = typeof row == "string" ? { _id: row } : row + return !processedRow._rev + ? addRev(fixRow(processedRow, ctx.params), tableId) + : fixRow(processedRow, ctx.params) + } + ) + + const rowDeletes = await Promise.all(targetRows) + if (rowDeletes) { + ctx.request.body.rows = rowDeletes + } + let { rows } = await quotas.addQuery( () => pickApi(tableId).bulkDestroy(ctx), {