Merge pull request #1567 from ItzNotABug/add-users-to-messages

Add users to message details
This commit is contained in:
Darshan
2025-01-28 18:05:24 +05:30
committed by GitHub
4 changed files with 123 additions and 29 deletions
@@ -41,13 +41,26 @@ export const load: LayoutLoad = async ({ params, depends }) => {
})
);
await Promise.allSettled(usersPromise);
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;
})
.catch(() => {
messageRecipients[userId] = null;
})
);
await Promise.allSettled([usersPromise, messageRecipientsPromise]);
return {
message,
topicsById,
targetsById,
usersById,
messageRecipients,
header: Header,
breadcrumbs: Breadcrumbs
};
@@ -33,7 +33,10 @@
<PushMessage message={$message} />
{/if}
<UpdateTopics message={$message} selectedTopicsById={data.topicsById} />
<UpdateTargets message={$message} selectedTargetsById={data.targetsById} />
<UpdateTargets
message={$message}
selectedTargetsById={data.targetsById}
selectedRecipients={data.messageRecipients} />
{#if $message.status !== 'processing'}
<Delete message={$message} />
{/if}
@@ -60,25 +60,21 @@
subject === message.data.subject &&
content === message.data.content &&
html === ((message.data['html'] ?? false) as boolean);
$: isDraft = message.status === 'draft';
</script>
<Form onSubmit={update}>
<CardGrid hideFooter={message.status !== 'draft'}>
<CardGrid hideFooter={!isDraft}>
<div class="grid-1-2-col-1 u-flex u-cross-center u-gap-16">
<Heading tag="h6" size="7">Message</Heading>
</div>
<svelte:fragment slot="aside">
<FormList>
<InputText
id="subject"
label="Subject"
disabled={message.status !== 'draft'}
bind:value={subject}></InputText>
<InputTextarea
id="message"
label="Message"
disabled={message.status !== 'draft'}
bind:value={content}></InputTextarea>
<InputText id="subject" label="Subject" disabled={!isDraft} bind:value={subject}
></InputText>
<InputTextarea id="message" label="Message" disabled={!isDraft} bind:value={content}
></InputTextarea>
<InputSwitch label="HTML mode" id="html" bind:value={html}>
<svelte:fragment slot="description">
Enable the HTML mode if your message contains HTML tags.
@@ -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;
@@ -93,20 +101,79 @@
}
}
$: 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={message.status != 'draft'}>
<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 message.status == 'draft'}
{#if isDraft}
<Button
text
noMargin
@@ -118,32 +185,47 @@
</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 message.status === 'draft'}
{#if isDraft}
<div
class="u-flex u-main-end"
style="--p-button-size: 1.25rem">
@@ -151,8 +233,8 @@
text
class="is-only-icon"
ariaLabel="delete"
disabled={message.status != 'draft'}
on:click={() => removeTarget(target.$id)}>
disabled={!isDraft}
on:click={() => removeTarget(source['$id'])}>
<span
class="icon-x u-font-size-20"
aria-hidden="true" />
@@ -169,9 +251,9 @@
<PaginationInline {sum} {limit} bind:offset />
</div>
</div>
{:else if message.status == 'draft'}
{: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.