mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Add a message detail page for email messages
This commit is contained in:
@@ -291,5 +291,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'
|
||||
}
|
||||
|
||||
@@ -48,7 +48,8 @@ export enum Dependencies {
|
||||
RUNTIMES = 'dependency:runtimes',
|
||||
CONSOLE_VARIABLES = 'dependency:console_variables',
|
||||
MESSAGING_PROVIDERS = 'dependency:messaging_providers',
|
||||
MESSAGING_PROVIDER = 'dependency:messaging_provider'
|
||||
MESSAGING_PROVIDER = 'dependency:messaging_provider',
|
||||
MESSAGING_MESSAGE = 'dependency:messaging_message'
|
||||
}
|
||||
|
||||
export const scopes: {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<svelte:head>
|
||||
<title>Message - Appwrite</title>
|
||||
</svelte:head>
|
||||
|
||||
<slot />
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
@@ -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>
|
||||
@@ -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} />
|
||||
@@ -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} />
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
@@ -49,7 +49,7 @@
|
||||
class="avatar"
|
||||
class:is-size-large={size === 'l'}
|
||||
class:is-size-small={size === 's'}>
|
||||
<span class={icon} style:--p-text-size={textSize} aria-hidden="true" />
|
||||
<span class={icon} style:font-size={textSize} aria-hidden="true" />
|
||||
</div>
|
||||
{/if}
|
||||
<slot>
|
||||
|
||||
Reference in New Issue
Block a user