From e2df7ae6db7556fd412c27d4e9e473333342ad86 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 24 Jun 2024 08:05:59 +0100 Subject: [PATCH] Improve bulk notifications and progress updates --- .../grid/controls/BulkDeleteHandler.svelte | 28 +++++++++------ .../controls/BulkDuplicationHandler.svelte | 11 ++++-- .../src/components/grid/stores/rows.js | 36 ++++++++----------- 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/packages/frontend-core/src/components/grid/controls/BulkDeleteHandler.svelte b/packages/frontend-core/src/components/grid/controls/BulkDeleteHandler.svelte index 9793f2ee27..8cf4492682 100644 --- a/packages/frontend-core/src/components/grid/controls/BulkDeleteHandler.svelte +++ b/packages/frontend-core/src/components/grid/controls/BulkDeleteHandler.svelte @@ -13,6 +13,7 @@ selectedCellCount, selectedRowCount, selectedCells, + rowLookupMap, } = getContext("grid") const duration = 260 @@ -20,17 +21,24 @@ let cellsModal let processing = false let progressPercentage = 0 + let promptQuantity = 0 - $: rowsToDelete = Object.entries($selectedRows) - .map(entry => $rows.find(x => x._id === entry[0])) + $: rowsToDelete = Object.keys($selectedRows) + .map(rowId => $rows[$rowLookupMap[rowId]]) .filter(x => x != null) const handleBulkDeleteRequest = () => { progressPercentage = 0 menu.actions.close() if ($selectedRowCount) { - rowsModal?.show() + if ($selectedRowCount === 1) { + bulkDeleteRows() + } else { + promptQuantity = $selectedRowCount + rowsModal?.show() + } } else if ($selectedCellCount) { + promptQuantity = $selectedCellCount cellsModal?.show() } } @@ -38,9 +46,11 @@ const bulkDeleteRows = async () => { processing = true const count = rowsToDelete.length - await rows.actions.deleteRows(rowsToDelete, progress => { - progressPercentage = progress * 100 - }) + await rows.actions.deleteRows(rowsToDelete) + // This is a real bulk delete endpoint so we don't need progress. + // We just animate it uo to 100 when we're done for consistency with other + // prompts. + progressPercentage = 100 await sleep(duration) $notifications.success(`Deleted ${count} row${count === 1 ? "" : "s"}`) processing = false @@ -76,8 +86,7 @@ onConfirm={bulkDeleteRows} size="M" > - Are you sure you want to delete {$selectedRowCount} - row{$selectedRowCount === 1 ? "" : "s"}? + Are you sure you want to delete {promptQuantity} rows? {#if processing} - Are you sure you want to delete {$selectedCellCount} - cell{$selectedCellCount === 1 ? "" : "s"}? + Are you sure you want to delete {promptQuantity} cells? {#if processing} { @@ -48,7 +49,12 @@ processing = false } - onMount(() => subscribe("request-bulk-duplicate", () => modal?.show())) + const handleBulkDuplicateRequest = () => { + promptQuantity = $selectedRowCount + modal?.show() + } + + onMount(() => subscribe("request-bulk-duplicate", handleBulkDuplicateRequest)) @@ -59,8 +65,7 @@ onConfirm={performDuplication} size="M" > - Are you sure you want to duplicate {$selectedRowCount} - row{$selectedRowCount === 1 ? "" : "s"}? + Are you sure you want to duplicate {promptQuantity} rows? {#if processing} { // Find index of last row const $rowLookupMap = get(rowLookupMap) const index = Math.max(...rowsToDupe.map(row => $rowLookupMap[row._id])) + const count = rowsToDupe.length // Clone and clean rows const clones = rowsToDupe.map(row => { @@ -336,7 +337,7 @@ export const createActions = context => { // Create rows let saved = [] let failed = 0 - for (let i = 0; i < clones.length; i++) { + for (let i = 0; i < count; i++) { try { saved.push(await datasource.actions.addRow(clones[i])) rowCacheMap[saved._id] = true @@ -345,7 +346,7 @@ export const createActions = context => { failed++ console.error("Duplicating row failed", error) } - progressCallback?.((i + 1) / clones.length) + progressCallback?.((i + 1) / count) } // Add to state @@ -356,15 +357,10 @@ export const createActions = context => { } // Notify user - if (saved.length) { - get(notifications).success( - `Duplicated ${saved.length} row${saved.length === 1 ? "" : "s"}` - ) - } if (failed) { - get(notifications).error( - `Failed to duplicate ${failed} row${failed === 1 ? "" : "s"}` - ) + get(notifications).error(`Failed to duplicate ${failed} of ${count} rows`) + } else if (saved.length) { + get(notifications).success(`Duplicated ${saved.length} rows`) } return saved } @@ -527,17 +523,18 @@ export const createActions = context => { const bulkUpdate = async (changeMap, progressCallback) => { const rowIds = Object.keys(changeMap || {}) - if (!rowIds.length) { + const count = rowIds.length + if (!count) { return } // Update rows let updated = [] let failed = 0 - for (let i = 0; i < rowIds.length; i++) { + for (let i = 0; i < count; i++) { const rowId = rowIds[i] if (!Object.keys(changeMap[rowId] || {}).length) { - progressCallback?.((i + 1) / rowIds.length) + progressCallback?.((i + 1) / count) continue } try { @@ -557,7 +554,7 @@ export const createActions = context => { failed++ console.error("Failed to update row", error) } - progressCallback?.((i + 1) / rowIds.length) + progressCallback?.((i + 1) / count) } // Update state @@ -573,15 +570,10 @@ export const createActions = context => { } // Notify user - if (updated.length) { - get(notifications).success( - `Updated ${updated.length} row${updated.length === 1 ? "" : "s"}` - ) - } if (failed) { - get(notifications).error( - `Failed to update ${failed} row${failed === 1 ? "" : "s"}` - ) + get(notifications).error(`Failed to update ${failed} of ${count} rows`) + } else if (updated.length) { + get(notifications).success(`Updated ${updated.length} rows`) } }