From c68fd85eeff2e416c694a34c3f0442d379d663e3 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 26 Oct 2025 14:07:34 +0530 Subject: [PATCH] add: `multiSelectTable` to database backups. --- src/lib/components/multiSelectTable.svelte | 166 +++---- .../database-[database]/backups/+page.svelte | 7 +- .../database-[database]/backups/table.svelte | 419 +++++++++--------- 3 files changed, 299 insertions(+), 293 deletions(-) diff --git a/src/lib/components/multiSelectTable.svelte b/src/lib/components/multiSelectTable.svelte index c79c496f3..7ccc0ba82 100644 --- a/src/lib/components/multiSelectTable.svelte +++ b/src/lib/components/multiSelectTable.svelte @@ -23,6 +23,7 @@ allowSelection = true, confirmDeletion = true, showSuccessNotification = true, + computeKey = 'multiSelectionTable', header, children, onDelete, @@ -33,6 +34,7 @@ resource: string; allowSelection?: boolean; confirmDeletion?: boolean; + computeKey?: string | number; showSuccessNotification?: boolean; columns: Array | number; header: Snippet<[root: TableRootProps]>; @@ -72,90 +74,92 @@ } - - - {@render header?.(root)} - - - {@render children(root)} - - -{#if allowSelection && selectedRows.length > 0} - - - - - {selectedRows.length > 1 ? getPluralResource() : resource} - selected - +{#key computeKey} + + + {@render header?.(root)} - - - + - - -{/if} + }}>Delete + + + {/if} -{#if allowSelection} - { - disableModal = true; - onDeleteError = null; + {#if allowSelection} + { + disableModal = true; + onDeleteError = null; - const state = await onDelete?.(selectedRows); - if (typeof state === 'string') { - disableModal = false; - onDeleteError = state || `Failed to delete ${resource}s`; - } else { - notifySuccess(); - selectedRows = []; - disableModal = false; - showConfirmDeletion = false; - } - }}> - - {@const selectionCount = selectedRows.length} - {#if deleteContent} - - {@render deleteContent(selectionCount)} - {:else} - Are you sure you want to delete {selectionCount} - {selectionCount > 1 ? getPluralResource() : resource}? - {/if} - + const state = await onDelete?.(selectedRows); + if (typeof state === 'string') { + disableModal = false; + onDeleteError = state || `Failed to delete ${resource}s`; + } else { + notifySuccess(); + selectedRows = []; + disableModal = false; + showConfirmDeletion = false; + } + }}> + + {@const selectionCount = selectedRows.length} + {#if deleteContent} + + {@render deleteContent(selectionCount)} + {:else} + Are you sure you want to delete {selectionCount} + {selectionCount > 1 ? getPluralResource() : resource}? + {/if} + - - {#if deleteContentNotice} - - {@render deleteContentNotice()} - {:else} - This action is irreversible. - {/if} - - -{/if} + + {#if deleteContentNotice} + + {@render deleteContentNotice()} + {:else} + This action is irreversible. + {/if} + + + {/if} +{/key} diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/+page.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/+page.svelte index 6c6a8de18..b9c1c57c8 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/+page.svelte @@ -69,11 +69,11 @@ await sdk .forProject(page.params.region, page.params.project) .backups.createArchive(['databases'], data.database.$id); + await invalidate(Dependencies.BACKUPS); addNotification({ type: 'success', message: 'Database backup has started' }); - invalidate(Dependencies.BACKUPS); trackEvent('click_manual_submit'); showFeedbackNotification(); } catch (error) { @@ -86,7 +86,7 @@ } }; - const trackEvents = (policies) => { + const trackEvents = (policies: UserBackupPolicy[]) => { policies.forEach((policy) => { let actualDay = null; const monthlyBackupFrequency = policy.monthlyBackupFrequency; @@ -139,7 +139,6 @@ ? `Backup policies have been created` : `${totalPolicies[0].label} policy has been created`; - // TODO: html isn't yet supported on Toast. addNotification({ isHtml: true, type: 'success', @@ -148,7 +147,7 @@ trackEvents(totalPolicies); - invalidate(Dependencies.BACKUPS); + await invalidate(Dependencies.BACKUPS); showFeedbackNotification(); } catch (err) { addNotification({ diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/table.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/table.svelte index 689afe74f..f9f5b7d0e 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/table.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/table.svelte @@ -1,5 +1,11 @@ - - + + {#snippet header(root)} {#each $columns as column} {column.title} {/each} - + {/snippet} - {#each data.backups.archives as backup, index} - {@const policy = policyDetails(backup.policyId)} - {@const retainedUntil = new Date( - new Date(policy?.$createdAt).getTime() + policy?.retention * 24 * 60 * 60 * 1000 - )} - {@const formattedRetainedUntil = `${retainedUntil.getDate()} ${retainedUntil.toLocaleString('en-US', { month: 'short' })}, ${retainedUntil.getFullYear()} ${retainedUntil.toLocaleTimeString('en-US', { hour12: false })}`} - - - - {cleanBackupName(backup)} - - - - {#if backup.status === 'completed'} - {calculateSize(backup.size)} - {:else} - - - {/if} - - - {@const backupStatus = getBackupStatus(backup)} - - - - - - -
- - - {policy?.name || 'Manual'} - - {policy - ? `Retained until: ${formattedRetainedUntil}` - : `Retained forever`} - -
-
- -
- - - - - {#if backup.status === 'completed'} + {#snippet children(root)} + {#each data.backups.archives as backup, index} + {@const policy = getPolicyDetails(backup.policyId)} + {@const retainedUntil = new Date( + new Date(policy?.$createdAt).getTime() + policy?.retention * 24 * 60 * 60 * 1000 + )} + {@const formattedRetainedUntil = `${retainedUntil.getDate()} ${retainedUntil.toLocaleString('en-US', { month: 'short' })}, ${retainedUntil.getFullYear()} ${retainedUntil.toLocaleTimeString('en-US', { hour12: false })}`} + + + + {getCleanBackupName(backup)} + + + + {#if backup.status === 'completed'} + {calculateSize(backup.size)} + {:else} + - + {/if} + + + {@const backupStatus = getBackupStatus(backup)} + + + + + + +
+ + + {policy?.name || 'Manual'} + + {policy + ? `Retained until: ${formattedRetainedUntil}` + : `Retained forever`} + +
+
+ +
+ + + + + {#if backup.status === 'completed'} + { + toggle(e); + showRestore = true; + selectedBackup = backup; + showDropdown[index] = false; + trackEvent(Click.BackupRestoreClick); + }}> + Restore + + {/if} { toggle(e); - showRestore = true; + copy(backup.$id); + showDropdown[index] = false; + trackEvent(Click.BackupCopyIdClick); + }}> + Copy ID + + { + toggle(e); + showDelete = true; selectedBackup = backup; showDropdown[index] = false; - trackEvent(Click.BackupRestoreClick); + trackEvent(Click.BackupDeleteClick); }}> - Restore + Delete - {/if} - { - toggle(e); - copy(backup.$id); - showDropdown[index] = false; - trackEvent(Click.BackupCopyIdClick); - }}> - Copy ID - - { - toggle(e); - showDelete = true; - selectedBackup = backup; - showDropdown[index] = false; - trackEvent(Click.BackupDeleteClick); - }}> - Delete - - - - -
-
-
- {/each} - - -{#if selectedBackups.length > 0} - - - - - {selectedBackups.length > 1 ? 'backups' : 'backup'} - selected - - - - - - - -{/if} +
+
+
+
+
+
+ {/each} + {/snippet} + + + onSubmit={async () => { + await deleteBackups([selectedBackup.$id]); + }}> - Are you sure you want to delete - {#if selectedBackups.length} - {selectedBackups.length} {selectedBackups.length > 1 ? 'backups' : 'backup'}? - {:else} - the {cleanBackupName(selectedBackup)} backup? - {/if} -
This action is irreversible. + Are you sure you want to delete the {getCleanBackupName(selectedBackup)} backup?
+ + This action is irreversible.
- {cleanBackupName(selectedBackup)} + {getCleanBackupName(selectedBackup)} @@ -374,6 +377,6 @@ - +