add: multiSelectTable to auth > teams.

This commit is contained in:
Darshan
2025-10-26 14:44:16 +05:30
parent 5b53e45cf2
commit 877c73d8e2
@@ -10,7 +10,9 @@
EmptySearch,
AvatarInitials,
SearchQuery,
PaginationWithLimit
PaginationWithLimit,
type DeleteOperationState,
MultiSelectionTable
} from '$lib/components';
import Create from '../createTeam.svelte';
import { goto } from '$app/navigation';
@@ -19,31 +21,16 @@
import type { Models } from '@appwrite.io/console';
import { writable } from 'svelte/store';
import { canWriteTeams } from '$lib/stores/roles';
import {
Icon,
Layout,
Table,
FloatingActionBar,
Badge,
Typography
} from '@appwrite.io/pink-svelte';
import { Icon, Layout, Table } from '@appwrite.io/pink-svelte';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import DualTimeView from '$lib/components/dualTimeView.svelte';
import { sdk } from '$lib/stores/sdk';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { Dependencies } from '$lib/constants';
import { addNotification } from '$lib/stores/notifications';
import { invalidate } from '$app/navigation';
import Confirm from '$lib/components/confirm.svelte';
import type { PageProps } from './$types';
export let data;
const region = page.params.region;
const project = page.params.project;
let selectedTeams: string[] = [];
let showDelete = false;
let deleting = false;
let { data }: PageProps = $props();
const columns = writable([
{ id: 'name', title: 'Name', type: 'string', width: { min: 200, max: 300 } },
@@ -52,37 +39,26 @@
]);
const teamCreated = async (event: CustomEvent<Models.Team<Record<string, unknown>>>) => {
await goto(`${base}/project-${region}-${project}/auth/teams/team-${event.detail.$id}`);
await goto(
`${base}/project-${page.params.region}-${page.params.project}/auth/teams/team-${event.detail.$id}`
);
};
async function handleDelete() {
showDelete = false;
deleting = true;
const promises = selectedTeams.map((teamId) =>
sdk.forProject(page.params.region, page.params.project).teams.delete(teamId)
);
async function handleDelete(selectedRows: string[]): Promise<DeleteOperationState> {
const promises = selectedRows.map((teamId) => {
return sdk.forProject(page.params.region, page.params.project).teams.delete({ teamId });
});
try {
await Promise.all(promises);
trackEvent(Submit.TeamDelete, {
total: selectedTeams.length
});
addNotification({
type: 'success',
message: `${selectedTeams.length} team${selectedTeams.length > 1 ? 's' : ''} deleted`
});
invalidate(Dependencies.TEAMS);
trackEvent(Submit.TeamDelete, { total: selectedRows.length });
return true;
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
trackError(error, Submit.TeamDelete);
return error.message;
} finally {
selectedTeams = [];
showDelete = false;
deleting = false;
await invalidate(Dependencies.TEAMS);
}
}
</script>
@@ -101,54 +77,47 @@
</Layout.Stack>
{#if data.teams.total}
<Table.Root
<MultiSelectionTable
resource="team"
columns={$columns}
allowSelection={$canWriteTeams}
bind:selectedRows={selectedTeams}
let:root>
<svelte:fragment slot="header" let:root>
onDelete={handleDelete}
allowSelection={$canWriteTeams}>
{#snippet header(root)}
{#each $columns as { id, title }}
<Table.Header.Cell column={id} {root}>{title}</Table.Header.Cell>
{/each}
</svelte:fragment>
{#each data.teams.teams as team (team.$id)}
<Table.Row.Link
{root}
href={`${base}/project-${region}-${project}/auth/teams/team-${team.$id}`}
id={team.$id}>
{#each $columns as column}
<Table.Cell column={column.id} {root}>
{#if column.id === 'name'}
<Layout.Stack direction="row" alignItems="center">
<AvatarInitials size="xs" name={team.name} />
<span class="u-trim">{team.name}</span>
</Layout.Stack>
{:else if column.id === 'members'}
{team.total} members
{:else if column.id === 'created'}
<DualTimeView time={team.$createdAt} />
{/if}
</Table.Cell>
{/each}
</Table.Row.Link>
{/each}
</Table.Root>
{/snippet}
{#if selectedTeams.length > 0}
<FloatingActionBar>
<svelte:fragment slot="start">
<Badge content={selectedTeams.length.toString()} />
<span>
{selectedTeams.length > 1 ? 'teams' : 'team'}
selected
</span>
</svelte:fragment>
<svelte:fragment slot="end">
<Button text on:click={() => (selectedTeams = [])}>Cancel</Button>
<Button secondary on:click={() => (showDelete = true)}>Delete</Button>
</svelte:fragment>
</FloatingActionBar>
{/if}
{#snippet children(root)}
{@const TableRowComponent = $canWriteTeams ? Table.Row.Link : Table.Row.Base}
{#each data.teams.teams as team (team.$id)}
{@const href = $canWriteTeams
? `${base}/project-${page.params.region}-${page.params.project}/auth/teams/team-${team.$id}`
: undefined}
<TableRowComponent {root} {href} id={team.$id}>
{#each $columns as column}
<Table.Cell column={column.id} {root}>
{#if column.id === 'name'}
<Layout.Stack direction="row" alignItems="center">
<AvatarInitials size="xs" name={team.name} />
<span class="u-trim">{team.name}</span>
</Layout.Stack>
{:else if column.id === 'members'}
{team.total} members
{:else if column.id === 'created'}
<DualTimeView time={team.$createdAt} />
{/if}
</Table.Cell>
{/each}
</TableRowComponent>
{/each}
{/snippet}
{#snippet deleteContentNotice()}
This action is irreversible and will permanently remove the selected teams and all
their memberships.
{/snippet}
</MultiSelectionTable>
<PaginationWithLimit
name="Teams"
@@ -157,7 +126,10 @@
total={data.teams.total} />
{:else if data.search}
<EmptySearch target="teams" search={data.search} hidePagination={data.teams.total === 0}>
<Button secondary size="s" href={`${base}/project-${region}-${project}/auth/teams`}>
<Button
size="s"
secondary
href={`${base}/project-${page.params.region}-${page.params.project}/auth/teams`}>
Clear Search
</Button>
</EmptySearch>
@@ -172,14 +144,3 @@
</Container>
<Create bind:showCreate={$showCreateTeam} on:created={teamCreated} />
<Confirm title="Delete teams" bind:open={showDelete} onSubmit={handleDelete} disabled={deleting}>
<Typography.Text>
Are you sure you want to delete <b>{selectedTeams.length}</b>
{selectedTeams.length > 1 ? 'teams' : 'team'}?
</Typography.Text>
<Typography.Text>
This action is irreversible and will permanently remove the selected teams and all their
memberships.
</Typography.Text>
</Confirm>