address comments: ui changes as per designs.

This commit is contained in:
Darshan
2025-01-28 17:53:05 +05:30
parent 695a557448
commit 11f15b1d44
4 changed files with 103 additions and 108 deletions
@@ -43,9 +43,14 @@ export const load: LayoutLoad = async ({ params, depends }) => {
const messageRecipients: Record<string, Models.User<Models.Preferences>> = {};
const messageRecipientsPromise = Object.values(message.users).map((userId) =>
sdk.forProject.users.get(userId).then((user) => {
messageRecipients[user.$id] = user;
})
sdk.forProject.users
.get(userId)
.then((user) => {
messageRecipients[user.$id] = user;
})
.catch(() => {
messageRecipients[userId] = null;
})
);
await Promise.allSettled([usersPromise, messageRecipientsPromise]);
@@ -12,7 +12,6 @@
import { MessagingProviderType } from '@appwrite.io/console';
import UpdateTopics from './updateTopics.svelte';
import UpdateTargets from './updateTargets.svelte';
import Recipients from './recipients.svelte';
import { onMount } from 'svelte';
export let data: PageData;
@@ -34,8 +33,10 @@
<PushMessage message={$message} />
{/if}
<UpdateTopics message={$message} selectedTopicsById={data.topicsById} />
<UpdateTargets message={$message} selectedTargetsById={data.targetsById} />
<Recipients message={$message} selectedRecipients={data.messageRecipients} />
<UpdateTargets
message={$message}
selectedTargetsById={data.targetsById}
selectedRecipients={data.messageRecipients} />
{#if $message.status !== 'processing'}
<Delete message={$message} />
{/if}
@@ -1,91 +0,0 @@
<script lang="ts">
import { MessagingProviderType, type Models } from '@appwrite.io/console';
import {
Table,
TableBody,
TableCell,
TableCellHead,
TableHeader,
TableRow
} from '$lib/elements/table';
import { CardGrid, EmptySearch, Heading, PaginationInline } from '$lib/components';
import { Button } from '$lib/elements/forms';
export let message: Models.Message;
export let selectedRecipients: Record<string, Models.User<Models.Preferences>>;
let offset = 0;
const limit = 10;
let messageRecipients = Object.values(selectedRecipients);
function getIdentifier(user: Models.User<Models.Preferences>): string {
switch (message.providerType) {
case MessagingProviderType.Email:
return user.email;
case MessagingProviderType.Sms:
return user.phone;
case MessagingProviderType.Push:
return (
user.targets?.find((target) => target.providerType === 'push')?.name ||
'Unknown identifier'
);
}
return 'Unknown identifier';
}
</script>
<CardGrid hideFooter={message.status !== 'draft'}>
<Heading tag="h6" size="7" id="variables">Users</Heading>
<svelte:fragment slot="aside">
{@const sum = messageRecipients.length}
{#if sum}
<div class="u-flex u-flex-vertical u-gap-24">
<Table noMargin noStyles>
<TableHeader>
<TableCellHead>Name</TableCellHead>
<TableCellHead>Identifier</TableCellHead>
</TableHeader>
<TableBody>
{#each messageRecipients.slice(offset, offset + limit) as recipient (recipient.$id)}
<TableRow>
<TableCell title="Name">
<div class="u-flex u-cross-center">
<span class="body-text-2 u-bold" data-private>
{recipient.name}
</span>
</div>
</TableCell>
<TableCell title="Identifier">
<span class="body-text-2" data-private>
{getIdentifier(recipient)}
</span>
</TableCell>
</TableRow>
{/each}
</TableBody>
</Table>
<div class="u-flex u-main-space-between">
<p class="text">Total users: {messageRecipients.length}</p>
<PaginationInline {sum} {limit} bind:offset />
</div>
</div>
{:else}
<EmptySearch hidePagination>
<div class="u-text-center">
No users have been selected.
<p>
Need a hand? Check out our
<Button
link
external
href="https://appwrite.io/docs/products/messaging"
text>
documentation
</Button>
.
</p>
</div>
</EmptySearch>
{/if}
</svelte:fragment>
</CardGrid>
@@ -8,7 +8,14 @@
TableHeader,
TableRow
} from '$lib/elements/table';
import { CardGrid, Heading, Empty, PaginationInline, EmptySearch } from '$lib/components';
import {
CardGrid,
Heading,
Empty,
PaginationInline,
EmptySearch,
Alert
} from '$lib/components';
import { onMount } from 'svelte';
import { sdk } from '$lib/stores/sdk';
import { invalidate } from '$app/navigation';
@@ -22,6 +29,7 @@
export let message: Models.Message & { data: Record<string, unknown> };
export let selectedTargetsById: Record<string, Models.Target>;
export let selectedRecipients: Record<string, Models.User<Models.Preferences>>;
let providerType: MessagingProviderType;
let offset = 0;
@@ -96,17 +104,74 @@
$: isDraft = message.status === 'draft';
$: disabled = symmetricDifference(targetIds, Object.keys(selectedTargetsById)).length === 0;
$: recipients = message.users.reduce((acc, userId) => {
const recipient = selectedRecipients[userId];
if (recipient) {
const target = recipient.targets.find((t) => t.providerType === message.providerType);
if (target) {
acc[userId] = {
$id: recipient.$id,
name: recipient.name,
identifier: target.identifier,
providerType: message.providerType
};
}
} else {
// user id exists but the user is null means the user account was deleted.
acc[userId] = null;
}
return acc;
}, {});
$: recipientsAvailable = recipientsCount > 0;
$: recipientsCount = Object.keys(recipients).filter((user) => user !== null).length;
$: hasDeletedUsers = Object.values(recipients).some((source) => source == null);
</script>
<Form onSubmit={update}>
<CardGrid hideFooter={!isDraft}>
<Heading tag="h6" size="7" id="variables">Targets</Heading>
<svelte:fragment slot="aside">
{@const sum = targetIds.length}
{#if sum}
{@const sum = targetIds.length || Object.values(recipients).length}
{@const dataSource =
targets.length > 0
? targets
: Object.values(recipients).filter((user) => user !== null)}
{#if hasDeletedUsers}
<div class:u-padding-block-end-16={dataSource.length}>
{#if hasDeletedUsers && !dataSource.length}
<Alert type="info">
<svelte:fragment slot="title"
>There are no targets to show</svelte:fragment>
This message was sent to users who are no longer available, so their information
cannot be displayed.
</Alert>
{:else}
<Alert
type="info"
dismissible={dataSource.length > 0}
on:dismiss={() => (hasDeletedUsers = false)}>
This message was sent to users who are no longer available, so their
information cannot be displayed.
</Alert>
{/if}
</div>
{/if}
{#if sum && dataSource.length}
<div class="u-flex u-cross-center u-main-space-between">
<div>
<div class="u-width-full-line u-flex u-main-space-between">
<span class="eyebrow-heading-3">Target</span>
{#if recipientsAvailable}
<span class="eyebrow-heading-3">Identifier</span>
<!-- empty header -->
<span class="eyebrow-heading-3" />
{/if}
</div>
{#if isDraft}
<Button
@@ -120,30 +185,45 @@
</Button>
{/if}
</div>
<div class="u-flex u-flex-vertical u-gap-24">
<Table noMargin noStyles>
<TableHeader>
<TableCellHead style="padding: 0" />
<TableCellHead width={40} style="padding: 0" />
{#if recipientsAvailable}
<TableCellHead style="padding: 0" />
{/if}
<TableCellHead width={25} style="padding: 0" />
</TableHeader>
<TableBody>
<TableRow />
{#each targets.slice(offset, offset + limit) as target (target.$id)}
<!-- dataSource contains objects with $id, providerType, name & identifier -->
{#each dataSource.slice(offset, offset + limit) as source (source['$id'])}
<TableRow>
<TableCell title="Target">
<div class="u-flex u-cross-center">
<span class="title">
<span class="u-line-height-1-5">
<span class="body-text-2" data-private>
{#if target.providerType === MessagingProviderType.Push}
{target.name}
{#if source['providerType'] === MessagingProviderType.Push}
{source['name']}
{:else}
{target.identifier}
{source['identifier']}
{/if}
</span>
</span></span>
</div>
</TableCell>
{#if recipientsAvailable}
<TableCell title="Identifier">
<span class="body-text-2" data-private>
{source['name']}
</span>
</TableCell>
{/if}
<TableCell title="Remove">
{#if isDraft}
<div
@@ -154,7 +234,7 @@
class="is-only-icon"
ariaLabel="delete"
disabled={!isDraft}
on:click={() => removeTarget(target.$id)}>
on:click={() => removeTarget(source['$id'])}>
<span
class="icon-x u-font-size-20"
aria-hidden="true" />
@@ -173,7 +253,7 @@
</div>
{:else if isDraft}
<Empty on:click={() => (showTargets = true)}>Add a target</Empty>
{:else}
{:else if !sum && !hasDeletedUsers}
<EmptySearch hidePagination>
<div class="u-text-center">
No targets have been selected.