add: multiSelectTable to keys/devKeys > table component.

This commit is contained in:
Darshan
2025-10-26 15:13:37 +05:30
parent 06eb186c1b
commit 5058d943d3
3 changed files with 72 additions and 69 deletions
+2 -2
View File
@@ -66,7 +66,7 @@
// this is kept very basic!
function getPluralResource() {
if (resource.endsWith('y')) {
if (resource.endsWith('ty')) {
return `${resource}ies`;
}
@@ -118,7 +118,7 @@
</FloatingActionBar>
{/if}
{#if allowSelection}
{#if allowSelection && confirmDeletion}
<Confirm
submissionLoader
confirmDeletion
@@ -59,7 +59,12 @@
}
</script>
<Confirm onSubmit={handleDelete} title={`Delete ${label} key`} bind:open={showDelete} bind:error>
<Confirm
bind:error
bind:open={showDelete}
submissionLoader
onSubmit={handleDelete}
title={`Delete ${label} key${keyIds.length > 1 ? 's' : ''}`}>
<p>
Are you sure you want to delete <b>{keyIds.length}</b>
{label} key{keyIds.length > 1 ? 's' : ''}?
@@ -2,27 +2,32 @@
import { base } from '$app/paths';
import { page } from '$app/state';
import { goto } from '$app/navigation';
import { Empty } from '$lib/components';
import { Button } from '$lib/elements/forms';
import { Empty, MultiSelectionTable } from '$lib/components';
import { canWriteKeys } from '$lib/stores/roles';
import type { Models } from '@appwrite.io/console';
import { diffDays } from '$lib/helpers/date';
import DualTimeView from '$lib/components/dualTimeView.svelte';
import { devKeyColumns, keyColumns, showDevKeysCreateModal } from '../store';
import { Badge, FloatingActionBar, Layout, Table } from '@appwrite.io/pink-svelte';
import { Badge, Layout, Table } from '@appwrite.io/pink-svelte';
import DeleteBatch from './deleteBatch.svelte';
import { capitalize } from '$lib/helpers/string';
import { getEffectiveScopes } from '../api-keys/scopes.svelte';
export let keyType: 'api' | 'dev' = 'api';
export let keys: Models.KeyList | Models.DevKeyList;
let {
keyType = 'api',
keys
}: {
keyType: 'api' | 'dev';
keys: Models.KeyList | Models.DevKeyList;
} = $props();
let showDeleteModal = false;
let selectedRows: string[] = [];
let selectedKeys = $state([]);
let showDeleteModal = $state(false);
const isApiKey = keyType === 'api';
const label = isApiKey ? 'API' : 'dev';
const slug = isApiKey ? 'api-keys' : 'dev-keys';
const columns = isApiKey ? $keyColumns : $devKeyColumns;
function getApiKeyScopeCount(key: Models.Key | Models.DevKey) {
const apiKey = key as Models.Key;
@@ -53,55 +58,65 @@
else
return 'Dev keys allow bypassing rate limits and CORS errors in your development environment.';
}
const columns = isApiKey ? $keyColumns : $devKeyColumns;
</script>
{#if keys.total}
<Table.Root let:root {columns} bind:selectedRows allowSelection={$canWriteKeys}>
<svelte:fragment slot="header" let:root>
<MultiSelectionTable
{columns}
confirmDeletion={false}
allowSelection={$canWriteKeys}
showSuccessNotification={false}
resource={`${capitalize(label)} key`}
onDelete={(selectedRows) => {
showDeleteModal = true;
selectedKeys = selectedRows;
}}>
{#snippet header(root)}
{#each columns as column}
<Table.Header.Cell column={column.id} {root}>{column.title}</Table.Header.Cell>
{/each}
</svelte:fragment>
{#each getKeys() as key (key.$id)}
<Table.Row.Link id={key.$id} href={`${slug}/${key.$id}`} {root}>
<Table.Cell {root}>
{key.name}
</Table.Cell>
<Table.Cell {root}>
{#if key.accessedAt}
<DualTimeView time={key.accessedAt} />
{:else}
never
{/if}
</Table.Cell>
<Table.Cell {root}>
{@const expiration = getExpiryDetails(key)}
<Layout.Stack gap="s" direction="row">
{#if key.expire}
<DualTimeView time={key.expire} />
{/snippet}
{#snippet children(root)}
{#each getKeys() as key (key.$id)}
<Table.Row.Link id={key.$id} href={`${slug}/${key.$id}`} {root}>
<Table.Cell {root}>
{key.name}
</Table.Cell>
<Table.Cell {root}>
{#if key.accessedAt}
<DualTimeView time={key.accessedAt} />
{:else}
never
{/if}
{#if expiration.status}
<Badge
size="s"
variant="secondary"
type={expiration.status}
content={expiration.message} />
{/if}
</Layout.Stack>
</Table.Cell>
{#if isApiKey}
<Table.Cell {root}>
{getApiKeyScopeCount(key)} Scopes
</Table.Cell>
{/if}
</Table.Row.Link>
{/each}
</Table.Root>
<Table.Cell {root}>
{@const expiration = getExpiryDetails(key)}
<Layout.Stack gap="s" direction="row">
{#if key.expire}
<DualTimeView time={key.expire} />
{:else}
never
{/if}
{#if expiration.status}
<Badge
size="s"
variant="secondary"
type={expiration.status}
content={expiration.message} />
{/if}
</Layout.Stack>
</Table.Cell>
{#if isApiKey}
<Table.Cell {root}>
{getApiKeyScopeCount(key)} Scopes
</Table.Cell>
{/if}
</Table.Row.Link>
{/each}
{/snippet}
</MultiSelectionTable>
{:else}
<Empty
single
@@ -109,9 +124,9 @@
href="https://appwrite.io/docs/advanced/platform/{slug}"
target="{label} key"
description={getDescription()}
on:click={() => {
on:click={async () => {
if (isApiKey) {
goto(
await goto(
`${base}/project-${page.params.region}-${page.params.project}/overview/${slug}/create`
);
} else {
@@ -120,21 +135,4 @@
}} />
{/if}
{#if selectedRows.length > 0}
<FloatingActionBar>
<svelte:fragment slot="start">
<Badge content={selectedRows.length.toString()} />
<span>
{capitalize(label)}
{selectedRows.length > 1 ? 'keys' : 'key'}
selected
</span>
</svelte:fragment>
<svelte:fragment slot="end">
<Button text on:click={() => (selectedRows = [])}>Cancel</Button>
<Button secondary on:click={() => (showDeleteModal = true)}>Delete</Button>
</svelte:fragment>
</FloatingActionBar>
{/if}
<DeleteBatch {keyType} bind:keyIds={selectedRows} bind:showDelete={showDeleteModal} />
<DeleteBatch {keyType} bind:keyIds={selectedKeys} bind:showDelete={showDeleteModal} />