Skip to content

Commit

Permalink
Add a message detail page for email messages
Browse files Browse the repository at this point in the history
  • Loading branch information
stnguyen90 committed Nov 30, 2023
1 parent e5a8e11 commit 81dbe6e
Show file tree
Hide file tree
Showing 12 changed files with 283 additions and 2 deletions.
3 changes: 2 additions & 1 deletion src/lib/actions/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,5 +286,6 @@ export enum Submit {
MessagingProviderCreate = 'submit_messaging_provider_create',
MessagingProviderDelete = 'submit_messaging_provider_delete',
MessagingProviderUpdate = 'submit_messaging_provider_update',
MessagingMessageCreate = 'submit_messaging_message_create'
MessagingMessageCreate = 'submit_messaging_message_create',
MessagingMessageDelete = 'submit_messaging_message_delete'
}
3 changes: 2 additions & 1 deletion src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export enum Dependencies {
COLLECTIONS = 'dependency:collections',
RUNTIMES = 'dependency:runtimes',
CONSOLE_VARIABLES = 'dependency:console_variables',
MESSAGING_PROVIDER = 'dependency:messaging_provider'
MESSAGING_PROVIDER = 'dependency:messaging_provider',
MESSAGING_MESSAGE = 'dependency:messaging_message'
}

export const scopes: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<svelte:head>
<title>Message - Appwrite</title>
</svelte:head>

<slot />
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { LayoutLoad } from './$types';
import Breadcrumbs from './breadcrumbs.svelte';
import Header from './header.svelte';
import { sdk } from '$lib/stores/sdk';
import { Dependencies } from '$lib/constants';
import { error } from '@sveltejs/kit';
import type { Message } from '../store';

export const load: LayoutLoad = async ({ params, depends }) => {
depends(Dependencies.MESSAGING_MESSAGE);

try {
const response: Message = await sdk.forProject.client.call(
'GET',
new URL(
`${sdk.forProject.client.config.endpoint}/messaging/messages/${params.message}`
),
{
'X-Appwrite-Project': sdk.forProject.client.config.project,
'content-type': 'application/json',
'X-Appwrite-Mode': 'admin'
}
);

return {
header: Header,
breadcrumbs: Breadcrumbs,
message: response
};
} catch (e) {
throw error(e.code, e.message);
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script lang="ts">
import { Container } from '$lib/layout';
import Delete from './delete.svelte';
import EmailPreview from './emailPreview.svelte';
import Overview from './overview.svelte';
import { message } from './store';
import { ProviderTypes } from '../providerType.svelte';
</script>

<Container>
<Overview />
{#if $message.providerType === ProviderTypes.Email}
<EmailPreview />
{/if}
<Delete />
</Container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script lang="ts">
import { Breadcrumbs } from '$lib/layout';
import { organization } from '$lib/stores/organization';
import { project } from '../../store';
import { message } from './store';
$: breadcrumbs = [
{
href: `/console/organization-${$organization.$id}`,
title: $organization.name
},
{
href: `/console/project-${$project.$id}`,
title: $project.name
},
{
href: `/console/project-${$project.$id}/messaging`,
title:
$message.data.title ?? $message.data.subject ?? $message.data.content ?? 'Message'
}
];
</script>

<Breadcrumbs {breadcrumbs} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script lang="ts">
import { BoxAvatar, CardGrid, Heading } from '$lib/components';
import { Button } from '$lib/elements/forms';
import { toLocaleDateTime } from '$lib/helpers/date';
import DeleteModal from './deleteModal.svelte';
import { message } from './store';
let showDelete = false;
</script>

<CardGrid>
<Heading tag="h6" size="7">Delete message</Heading>
<p>
The message will be permanently deleted, including all data associated with this message.
This action is irreversible.
</p>
<svelte:fragment slot="aside">
<BoxAvatar>
<svelte:fragment slot="title">
<h6 class="u-bold u-trim-1" data-private>
{$message.data.title ??
$message.data.subject ??
$message.data.content ??
'Message'}
</h6>
</svelte:fragment>
<p>
Last updated: {toLocaleDateTime($message.$updatedAt)}
</p>
</BoxAvatar>
</svelte:fragment>

<svelte:fragment slot="actions">
<Button secondary on:click={() => (showDelete = true)} event="delete_file">Delete</Button>
</svelte:fragment>
</CardGrid>

<DeleteModal bind:show={showDelete} />
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { base } from '$app/paths';
import { page } from '$app/stores';
import { Modal } from '$lib/components';
import { Button } from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
import { message } from './store';
export let show = false;
const deleteMessage = async () => {
try {
await sdk.forProject.client.call(
'DELETE',
new URL(
`${sdk.forProject.client.config.endpoint}/messaging/messages/${$message.$id}`
),
{
'X-Appwrite-Project': sdk.forProject.client.config.project,
'content-type': 'application/json',
'X-Appwrite-Mode': 'admin'
}
);
show = false;
addNotification({
type: 'success',
message: `Message has been deleted`
});
trackEvent(Submit.MessagingMessageDelete);
await goto(`${base}/console/project-${$page.params.project}/messaging`);
} catch (error) {
addNotification({
type: 'error',
message: error.message
});
trackError(error, Submit.MessagingMessageDelete);
}
};
</script>

<Modal
title="Delete message"
bind:show
onSubmit={deleteMessage}
icon="exclamation"
state="warning"
headerDivider={false}>
<p data-private>Are you sure you want to delete this message?</p>
<svelte:fragment slot="footer">
<Button text on:click={() => (show = false)}>Cancel</Button>
<Button secondary submit>Delete</Button>
</svelte:fragment>
</Modal>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<script lang="ts">
import { CardGrid, Heading } from '$lib/components';
import { FormList, InputText, InputTextarea } from '$lib/elements/forms';
import { message } from './store';
</script>

<CardGrid>
<div class="grid-1-2-col-1 u-flex u-cross-center u-gap-16">
<Heading tag="h6" size="7">Preview</Heading>
</div>
<svelte:fragment slot="aside">
<FormList>
<InputText
id="subject"
label="Subject"
disabled={true}
bind:value={$message.data.subject}>
</InputText>
<InputTextarea
id="message"
label="Message"
disabled={true}
bind:value={$message.data.content}>
</InputTextarea>
</FormList>
</svelte:fragment>

<svelte:fragment slot="actions">
<!-- TODO: Add support for editing draft messages -->
<!-- <Button disabled={$message.status !== 'draft'} on:click={() => console.log('click')}
>Edit message</Button> -->
</svelte:fragment>
</CardGrid>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script lang="ts">
import { page } from '$app/stores';
import { Id } from '$lib/components';
import { Cover, CoverTitle } from '$lib/layout';
import { message } from './store';
const projectId = $page.params.project;
</script>

<Cover>
<svelte:fragment slot="header">
<CoverTitle href={`/console/project-${projectId}/messaging`}>
{$message.data.title ?? $message.data.subject ?? $message.data.content ?? 'Message'}
</CoverTitle>
<Id value={$message.$id} event="message">{$message.$id}</Id>
</svelte:fragment>
</Cover>
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<script lang="ts">
import { CardGrid, Heading } from '$lib/components';
import { toLocaleDateTime } from '$lib/helpers/date';
import { message } from './store';
import ProviderType, { ProviderTypes } from '../providerType.svelte';
import MessageStatusPill from '../messageStatusPill.svelte';
let scheduledAt: string = '';
if ($message.status === 'sent') {
scheduledAt = $message.deliveredAt;
} else if ($message.status === 'scheduled') {
scheduledAt = $message.scheduledAt;
}
let providerType = 'Invalid provider type';
switch ($message.providerType) {
case ProviderTypes.Email:
providerType = 'Email';
break;
case ProviderTypes.Sms:
providerType = 'SMS';
break;
case ProviderTypes.Push:
providerType = 'Push';
break;
}
</script>

<CardGrid>
<div class="grid-1-2-col-1 u-flex u-cross-center u-gap-16" data-private>
<ProviderType type={$message.providerType} size="l">
<Heading tag="h6" size="7">{providerType}</Heading>
</ProviderType>
</div>
<svelte:fragment slot="aside">
<div class="u-flex u-main-space-between">
<div data-private>
<p class="title">Created: {toLocaleDateTime($message.$createdAt)}</p>
<p class="title">Scheduled at: {toLocaleDateTime(scheduledAt)}</p>
</div>
<div class="u-flex u-flex-vertical u-cross-end">
<MessageStatusPill status={$message.status} />
</div>
</div>
</svelte:fragment>

<svelte:fragment slot="actions">
<!-- TODO: Add support for editing draft messages -->
<!-- <Button disabled={$message.status !== 'draft'} on:click={() => console.log('click')}
>Edit message</Button> -->
</svelte:fragment>
</CardGrid>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { derived } from 'svelte/store';
import { page } from '$app/stores';
import type { Message } from '../store';

export const message = derived(page, ($page) => $page.data.message as Message);

0 comments on commit 81dbe6e

Please sign in to comment.