mirror of
https://github.com/appwrite/console.git
synced 2026-04-07 19:17:46 +00:00
fix: templates not loading.
This commit is contained in:
+1
-1
@@ -26,7 +26,7 @@
|
||||
"@appwrite.io/pink-icons": "0.25.0",
|
||||
"@appwrite.io/pink-icons-svelte": "^2.0.0-RC.1",
|
||||
"@appwrite.io/pink-legacy": "^1.0.3",
|
||||
"@appwrite.io/pink-svelte": "https://try-module.cloud/-/@appwrite/@appwrite.io/pink-svelte@f1287d5",
|
||||
"@appwrite.io/pink-svelte": "https://try-module.cloud/-/@appwrite/@appwrite.io/pink-svelte@4b056c8",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@sentry/sveltekit": "^8.38.0",
|
||||
"@stripe/stripe-js": "^3.5.0",
|
||||
|
||||
Generated
+5
-5
@@ -24,8 +24,8 @@ importers:
|
||||
specifier: ^1.0.3
|
||||
version: 1.0.3
|
||||
'@appwrite.io/pink-svelte':
|
||||
specifier: https://try-module.cloud/-/@appwrite/@appwrite.io/pink-svelte@f1287d5
|
||||
version: https://try-module.cloud/-/@appwrite/%40appwrite.io%2Fpink-svelte@f1287d5(svelte@5.25.3)
|
||||
specifier: https://try-module.cloud/-/@appwrite/@appwrite.io/pink-svelte@4b056c8
|
||||
version: https://try-module.cloud/-/@appwrite/%40appwrite.io%2Fpink-svelte@4b056c8(svelte@5.25.3)
|
||||
'@popperjs/core':
|
||||
specifier: ^2.11.8
|
||||
version: 2.11.8
|
||||
@@ -278,8 +278,8 @@ packages:
|
||||
'@appwrite.io/pink-legacy@1.0.3':
|
||||
resolution: {integrity: sha512-GGde5fmPhs+s6/3aFeMPc/kKADG/gTFkYQSy6oBN8pK0y0XNCLrZZgBv+EBbdhwdtqVEWXa0X85Mv9w7jcIlwQ==}
|
||||
|
||||
'@appwrite.io/pink-svelte@https://try-module.cloud/-/@appwrite/%40appwrite.io%2Fpink-svelte@f1287d5':
|
||||
resolution: {tarball: https://try-module.cloud/-/@appwrite/%40appwrite.io%2Fpink-svelte@f1287d5}
|
||||
'@appwrite.io/pink-svelte@https://try-module.cloud/-/@appwrite/%40appwrite.io%2Fpink-svelte@4b056c8':
|
||||
resolution: {tarball: https://try-module.cloud/-/@appwrite/%40appwrite.io%2Fpink-svelte@4b056c8}
|
||||
version: 2.0.0-RC.2
|
||||
peerDependencies:
|
||||
svelte: ^4.0.0
|
||||
@@ -3635,7 +3635,7 @@ snapshots:
|
||||
'@appwrite.io/pink-icons': 1.0.0
|
||||
the-new-css-reset: 1.11.3
|
||||
|
||||
'@appwrite.io/pink-svelte@https://try-module.cloud/-/@appwrite/%40appwrite.io%2Fpink-svelte@f1287d5(svelte@5.25.3)':
|
||||
'@appwrite.io/pink-svelte@https://try-module.cloud/-/@appwrite/%40appwrite.io%2Fpink-svelte@4b056c8(svelte@5.25.3)':
|
||||
dependencies:
|
||||
'@appwrite.io/pink-icons-svelte': 2.0.0-RC.1(svelte@5.25.3)
|
||||
'@floating-ui/dom': 1.6.13
|
||||
|
||||
@@ -1,4 +1,14 @@
|
||||
<script context="module" lang="ts">
|
||||
import type {
|
||||
SmsTemplateLocale,
|
||||
SmsTemplateType,
|
||||
EmailTemplateType,
|
||||
EmailTemplateLocale
|
||||
} from '@appwrite.io/console';
|
||||
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
|
||||
export async function loadEmailTemplate(projectId: string, type: string, locale: string) {
|
||||
try {
|
||||
// TODO: fix TemplateType and TemplateLocale typing once SDK is updated
|
||||
@@ -35,49 +45,43 @@
|
||||
import { base } from '$app/paths';
|
||||
import { CardGrid } from '$lib/components';
|
||||
import { Container } from '$lib/layout';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import EmailVerificationTemplate from './emailVerificationTemplate.svelte';
|
||||
import EmailMagicUrlTemplate from './emailMagicUrlTemplate.svelte';
|
||||
import EmailRecoveryTemplate from './emailRecoveryTemplate.svelte';
|
||||
import EmailInviteTemplate from './emailInviteTemplate.svelte';
|
||||
import Email2FaTemplate from './email2FATemplate.svelte';
|
||||
import EmailSessionAlertTemplate from './emailSessionAlertTemplate.svelte';
|
||||
|
||||
// import SmsVerificationTemplate from './smsVerificationTemplate.svelte';
|
||||
// import SmsLoginTemplate from './smsLoginTemplate.svelte';
|
||||
// import { baseEmailTemplate, baseSmsTemplate, emailTemplate, smsTemplate } from './store';
|
||||
import { baseEmailTemplate, emailTemplate } from './store';
|
||||
import { baseEmailTemplate, emailTemplate, templates } from './store';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { currentPlan } from '$lib/stores/organization';
|
||||
import EmailSignature from './emailSignature.svelte';
|
||||
import { isCloud } from '$lib/system';
|
||||
import type {
|
||||
SmsTemplateLocale,
|
||||
SmsTemplateType,
|
||||
EmailTemplateType,
|
||||
EmailTemplateLocale
|
||||
} from '@appwrite.io/console';
|
||||
import { Accordion, Alert, Badge, Layout, Link, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
export let data;
|
||||
|
||||
let emailOpen = 'verification';
|
||||
$: emailVerificationOpen = emailOpen === 'verification';
|
||||
$: emailMagicSessionOpen = emailOpen === 'magicSession';
|
||||
$: emailOtpSessionOpen = emailOpen === 'otpSession';
|
||||
$: emailResetPassword = emailOpen === 'recovery';
|
||||
$: emailInviteUser = emailOpen === 'invitation';
|
||||
$: email2FAVerificationOpen = emailOpen === 'mfaChallenge';
|
||||
$: emailSessionAlertOpen = emailOpen === 'sessionAlert';
|
||||
let templateType = null;
|
||||
let isTemplateLoading = false;
|
||||
let openStates = Object.fromEntries(templates.map(({ key }) => [key, false]));
|
||||
|
||||
openEmail('verification');
|
||||
loadTemplateFor('verification');
|
||||
|
||||
async function loadTemplateFor(type: string) {
|
||||
// return, already loaded!
|
||||
if (templateType === type) return;
|
||||
|
||||
templateType = type;
|
||||
isTemplateLoading = true;
|
||||
|
||||
async function openEmail(type: string) {
|
||||
type === emailOpen ? (emailOpen = null) : (emailOpen = type);
|
||||
$emailTemplate = await loadEmailTemplate(page.params.project, type, 'en');
|
||||
$baseEmailTemplate = { ...$emailTemplate };
|
||||
|
||||
isTemplateLoading = false;
|
||||
}
|
||||
|
||||
function toggleAccordion(type: string) {
|
||||
for (const key in openStates) {
|
||||
openStates[key] = false;
|
||||
}
|
||||
|
||||
openStates[type] = true;
|
||||
|
||||
loadTemplateFor(type);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -109,95 +113,21 @@
|
||||
Learn more
|
||||
</Link.Anchor>
|
||||
<svelte:fragment slot="aside">
|
||||
<Layout.Stack gap="none">
|
||||
<Accordion
|
||||
title="Verification"
|
||||
bind:open={emailVerificationOpen}
|
||||
on:click={() => openEmail('verification')}>
|
||||
<Layout.Stack>
|
||||
<Typography.Text>
|
||||
Send a verification email to users that sign in with their email and
|
||||
password.
|
||||
</Typography.Text>
|
||||
<EmailVerificationTemplate />
|
||||
</Layout.Stack>
|
||||
</Accordion>
|
||||
<Accordion
|
||||
title="Magic URL"
|
||||
bind:open={emailMagicSessionOpen}
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
openEmail('magicSession');
|
||||
}}>
|
||||
<Layout.Stack>
|
||||
<Typography.Text>
|
||||
Send an email to users that sign in with a magic URL.
|
||||
</Typography.Text>
|
||||
<EmailMagicUrlTemplate />
|
||||
</Layout.Stack>
|
||||
</Accordion>
|
||||
<Accordion
|
||||
title="OTP session"
|
||||
bind:open={emailOtpSessionOpen}
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
openEmail('otpSession');
|
||||
}}>
|
||||
<Layout.Stack>
|
||||
<Typography.Text>
|
||||
Send an email to users that sign in with a email OTP.</Typography.Text>
|
||||
<EmailMagicUrlTemplate />
|
||||
</Layout.Stack>
|
||||
</Accordion>
|
||||
<Accordion
|
||||
title="Reset password"
|
||||
bind:open={emailResetPassword}
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
openEmail('recovery');
|
||||
}}>
|
||||
<Layout.Stack>
|
||||
<Typography.Text>
|
||||
Send a recovery email to users that forget their password.</Typography.Text>
|
||||
<EmailRecoveryTemplate /></Layout.Stack>
|
||||
</Accordion>
|
||||
<Accordion
|
||||
title="Invite user"
|
||||
bind:open={emailInviteUser}
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
openEmail('invitation');
|
||||
}}>
|
||||
<Layout.Stack>
|
||||
<Typography.Text>
|
||||
Send an invitation email to become a member of your project.</Typography.Text>
|
||||
<EmailInviteTemplate />
|
||||
</Layout.Stack>
|
||||
</Accordion>
|
||||
<Accordion
|
||||
title="2FA verification"
|
||||
bind:open={email2FAVerificationOpen}
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
openEmail('mfaChallenge');
|
||||
}}>
|
||||
<Layout.Stack>
|
||||
<Typography.Text>
|
||||
Send a two-factor authentication email to a user.</Typography.Text>
|
||||
<Email2FaTemplate /></Layout.Stack>
|
||||
</Accordion>
|
||||
<Accordion
|
||||
title="Session alert"
|
||||
bind:open={emailSessionAlertOpen}
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
openEmail('sessionAlert');
|
||||
}}>
|
||||
<Layout.Stack>
|
||||
<Typography.Text>
|
||||
Send an email to users when a new session is created.</Typography.Text>
|
||||
<EmailSessionAlertTemplate /></Layout.Stack>
|
||||
</Accordion>
|
||||
<Layout.Stack gap="s">
|
||||
{#each templates as section (section.key)}
|
||||
<Accordion
|
||||
title={section.title}
|
||||
hideDivider={section.hideDivider}
|
||||
bind:open={openStates[section.key]}
|
||||
on:toggle={(event) => event.detail && toggleAccordion(section.key)}>
|
||||
<Layout.Stack>
|
||||
<Typography.Text>{section.description}</Typography.Text>
|
||||
<svelte:component
|
||||
this={section.component}
|
||||
loading={isTemplateLoading} />
|
||||
</Layout.Stack>
|
||||
</Accordion>
|
||||
{/each}
|
||||
</Layout.Stack>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="actions">
|
||||
|
||||
+7
-5
@@ -9,13 +9,15 @@
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Layout, Card } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
export let loading = false;
|
||||
|
||||
let locale = 'en';
|
||||
let loading = false;
|
||||
let isUpdating = false;
|
||||
const projectId = page.params.project;
|
||||
|
||||
async function onLocaleChange() {
|
||||
const timeout = setTimeout(() => {
|
||||
loading = true;
|
||||
isUpdating = true;
|
||||
}, 1000);
|
||||
try {
|
||||
const template = await loadEmailTemplate(projectId, 'mfaChallenge', locale);
|
||||
@@ -30,7 +32,7 @@
|
||||
});
|
||||
} finally {
|
||||
clearTimeout(timeout);
|
||||
loading = false;
|
||||
isUpdating = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -38,7 +40,7 @@
|
||||
<Card.Base variant="secondary" padding="s">
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<EmailTemplate {loading} {isUpdating}>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{otp}}'}>{'{{otp}}'}</Id>
|
||||
|
||||
+7
-5
@@ -9,13 +9,15 @@
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Layout, Card } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
export let loading = false;
|
||||
|
||||
let locale = 'en';
|
||||
let loading = false;
|
||||
let isUpdating = false;
|
||||
const projectId = page.params.project;
|
||||
|
||||
async function onLocaleChange() {
|
||||
const timeout = setTimeout(() => {
|
||||
loading = true;
|
||||
isUpdating = true;
|
||||
}, 1000);
|
||||
try {
|
||||
const template = await loadEmailTemplate(projectId, 'invitation', locale);
|
||||
@@ -30,7 +32,7 @@
|
||||
});
|
||||
} finally {
|
||||
clearTimeout(timeout);
|
||||
loading = false;
|
||||
isUpdating = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -38,7 +40,7 @@
|
||||
<Card.Base variant="secondary" padding="s">
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<EmailTemplate {loading} {isUpdating}>
|
||||
<Id value={'{{team}}'}>{'{{team}}'}</Id>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
|
||||
+6
-5
@@ -9,14 +9,15 @@
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Layout, Card } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
export let loading = false;
|
||||
|
||||
let locale = 'en';
|
||||
let loading = false;
|
||||
let isUpdating = false;
|
||||
const projectId = page.params.project;
|
||||
|
||||
async function onLocaleChange() {
|
||||
const timeout = setTimeout(() => {
|
||||
loading = true;
|
||||
isUpdating = true;
|
||||
}, 1000);
|
||||
try {
|
||||
const template = await loadEmailTemplate(projectId, 'magicSession', locale);
|
||||
@@ -32,7 +33,7 @@
|
||||
} finally {
|
||||
clearTimeout(timeout);
|
||||
|
||||
loading = false;
|
||||
isUpdating = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -40,7 +41,7 @@
|
||||
<Card.Base variant="secondary" padding="s">
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<EmailTemplate {loading} {isUpdating}>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{redirect}}'}>{'{{redirect}}'}</Id>
|
||||
|
||||
+6
-5
@@ -9,14 +9,15 @@
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Layout, Card } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
export let loading = false;
|
||||
|
||||
let locale = 'en';
|
||||
let loading = false;
|
||||
let isUpdating = false;
|
||||
const projectId = page.params.project;
|
||||
|
||||
async function onLocaleChange() {
|
||||
const timeout = setTimeout(() => {
|
||||
loading = true;
|
||||
isUpdating = true;
|
||||
}, 1000);
|
||||
try {
|
||||
const template = await loadEmailTemplate(projectId, 'recovery', locale);
|
||||
@@ -30,8 +31,8 @@
|
||||
message: error.message
|
||||
});
|
||||
} finally {
|
||||
isUpdating = false;
|
||||
clearTimeout(timeout);
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -39,7 +40,7 @@
|
||||
<Card.Base variant="secondary" padding="s">
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<EmailTemplate {loading} {isUpdating}>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{redirect}}'}>{'{{redirect}}'}</Id>
|
||||
|
||||
+7
-5
@@ -9,13 +9,15 @@
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Layout, Card } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
export let loading = false;
|
||||
|
||||
let locale = 'en';
|
||||
let loading = false;
|
||||
let isUpdating = false;
|
||||
const projectId = page.params.project;
|
||||
|
||||
async function onLocaleChange() {
|
||||
const timeout = setTimeout(() => {
|
||||
loading = true;
|
||||
isUpdating = true;
|
||||
}, 1000);
|
||||
try {
|
||||
const template = await loadEmailTemplate(projectId, 'sessionalert', locale);
|
||||
@@ -30,7 +32,7 @@
|
||||
});
|
||||
} finally {
|
||||
clearTimeout(timeout);
|
||||
loading = false;
|
||||
isUpdating = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -38,7 +40,7 @@
|
||||
<Card.Base variant="secondary" padding="s">
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<EmailTemplate {loading} {isUpdating}>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{device}}'}>{'{{device}}'}</Id>
|
||||
|
||||
+61
-58
@@ -10,10 +10,12 @@
|
||||
import type { EmailTemplateLocale, EmailTemplateType } from '@appwrite.io/console';
|
||||
import { Icon, Layout, Tooltip, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
|
||||
import TemplateSkeleton from './templateSkeleton.svelte';
|
||||
|
||||
export let loading = false;
|
||||
let openResetModal = false;
|
||||
export let isUpdating = false;
|
||||
|
||||
let openResetModal = false;
|
||||
let eventType = Submit.EmailUpdateInviteTemplate;
|
||||
|
||||
async function saveEmailTemplate() {
|
||||
@@ -79,69 +81,70 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: isButtonDisabled = deepEqual($emailTemplate, $baseEmailTemplate);
|
||||
$: isSmtpEnabled = $project?.smtpEnabled;
|
||||
$: isButtonDisabled = deepEqual($emailTemplate, $baseEmailTemplate);
|
||||
</script>
|
||||
|
||||
{#if loading}
|
||||
<div
|
||||
class="u-position-absolute u-width-full-line u-flex u-flex-vertical u-main-center u-cross-center u-gap-16 u-margin-block-start-32"
|
||||
style="inset-inline-start: 0;">
|
||||
<div class="loader"></div>
|
||||
<p class="text">Loading template...</p>
|
||||
</div>
|
||||
{/if}
|
||||
<div class:u-opacity-0={loading} style={loading ? 'pointer-events: none' : ''}>
|
||||
<div class:u-opacity-0={isUpdating} style={isUpdating ? 'pointer-events: none' : ''}>
|
||||
<Form onSubmit={saveEmailTemplate}>
|
||||
<Layout.Stack>
|
||||
<InputText
|
||||
id="senderName"
|
||||
label="Sender name"
|
||||
bind:value={$emailTemplate.senderName}
|
||||
placeholder="Enter sender name"
|
||||
disabled={!isSmtpEnabled} />
|
||||
<InputEmail
|
||||
bind:value={$emailTemplate.senderEmail}
|
||||
id="senderEmail"
|
||||
label="Sender email"
|
||||
placeholder="Enter sender email"
|
||||
disabled={!isSmtpEnabled} />
|
||||
<InputEmail
|
||||
bind:value={$emailTemplate.replyTo}
|
||||
id="replyTo"
|
||||
label="Reply to"
|
||||
placeholder="noreply@appwrite.io" />
|
||||
{#if $$slots.default}
|
||||
<p class="text">
|
||||
Click to copy variables for the fields below. Learn more <a
|
||||
class="link"
|
||||
href="https://appwrite.io/docs/advanced/platform/message-templates">here</a
|
||||
>.
|
||||
</p>
|
||||
<Layout.Stack direction="row">
|
||||
<slot />
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
<InputText
|
||||
bind:value={$emailTemplate.subject}
|
||||
id="subject"
|
||||
label="Subject"
|
||||
placeholder="Enter subject" />
|
||||
{#if loading}
|
||||
<TemplateSkeleton count={3} />
|
||||
{:else}
|
||||
<InputText
|
||||
id="senderName"
|
||||
label="Sender name"
|
||||
bind:value={$emailTemplate.senderName}
|
||||
placeholder="Enter sender name"
|
||||
disabled={!isSmtpEnabled} />
|
||||
|
||||
<InputTextarea
|
||||
bind:value={$emailTemplate.message}
|
||||
id="message"
|
||||
label="Message"
|
||||
placeholder="Enter your message"
|
||||
readonly={!isSmtpEnabled}
|
||||
rows={8}>
|
||||
<Tooltip slot="info" maxWidth="15rem">
|
||||
<Icon icon={IconInfo} size="s" />
|
||||
<Typography.Caption variant="400" slot="tooltip">
|
||||
Set up an SMTP server to edit the message body
|
||||
</Typography.Caption>
|
||||
</Tooltip>
|
||||
</InputTextarea>
|
||||
<InputEmail
|
||||
bind:value={$emailTemplate.senderEmail}
|
||||
id="senderEmail"
|
||||
label="Sender email"
|
||||
placeholder="Enter sender email"
|
||||
disabled={!isSmtpEnabled} />
|
||||
|
||||
<InputEmail
|
||||
bind:value={$emailTemplate.replyTo}
|
||||
id="replyTo"
|
||||
label="Reply to"
|
||||
placeholder="noreply@appwrite.io" />
|
||||
|
||||
{#if $$slots.default}
|
||||
<p class="text">
|
||||
Click to copy variables for the fields below. Learn more <a
|
||||
class="link"
|
||||
href="https://appwrite.io/docs/advanced/platform/message-templates"
|
||||
>here</a
|
||||
>.
|
||||
</p>
|
||||
<Layout.Stack direction="row">
|
||||
<slot />
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
|
||||
<InputText
|
||||
bind:value={$emailTemplate.subject}
|
||||
id="subject"
|
||||
label="Subject"
|
||||
placeholder="Enter subject" />
|
||||
|
||||
<InputTextarea
|
||||
bind:value={$emailTemplate.message}
|
||||
id="message"
|
||||
label="Message"
|
||||
placeholder="Enter your message"
|
||||
readonly={!isSmtpEnabled}
|
||||
rows={8}>
|
||||
<Tooltip slot="info" maxWidth="15rem">
|
||||
<Icon icon={IconInfo} size="s" />
|
||||
<Typography.Caption variant="400" slot="tooltip">
|
||||
Set up an SMTP server to edit the message body
|
||||
</Typography.Caption>
|
||||
</Tooltip>
|
||||
</InputTextarea>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
<div class="u-sep-block-start u-margin-block-start-24"></div>
|
||||
<div class="u-flex u-gap-16 u-main-end u-margin-block-start-24">
|
||||
|
||||
+6
-5
@@ -9,14 +9,15 @@
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Layout, Card } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
export let loading = false;
|
||||
|
||||
let locale = 'en';
|
||||
let loading = false;
|
||||
let isUpdating = false;
|
||||
const projectId = page.params.project;
|
||||
|
||||
async function onLocaleChange() {
|
||||
const timeout = setTimeout(() => {
|
||||
loading = true;
|
||||
isUpdating = true;
|
||||
}, 1000);
|
||||
try {
|
||||
const template = await loadEmailTemplate(projectId, 'verification', locale);
|
||||
@@ -31,7 +32,7 @@
|
||||
});
|
||||
} finally {
|
||||
clearTimeout(timeout);
|
||||
loading = false;
|
||||
isUpdating = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -39,7 +40,7 @@
|
||||
<Card.Base variant="secondary" padding="s">
|
||||
<Layout.Stack gap="l">
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<EmailTemplate {loading} {isUpdating}>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{redirect}}'}>{'{{redirect}}'}</Id>
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import { page } from '$app/stores';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { derived, writable } from 'svelte/store';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
// component imports
|
||||
import Email2FaTemplate from './email2FATemplate.svelte';
|
||||
import EmailInviteTemplate from './emailInviteTemplate.svelte';
|
||||
import EmailRecoveryTemplate from './emailRecoveryTemplate.svelte';
|
||||
import EmailMagicUrlTemplate from './emailMagicUrlTemplate.svelte';
|
||||
import EmailVerificationTemplate from './emailVerificationTemplate.svelte';
|
||||
import EmailSessionAlertTemplate from './emailSessionAlertTemplate.svelte';
|
||||
|
||||
export const localeCodes = derived(page, ($page) => $page.data.localeCodes as Models.LocaleCode[]);
|
||||
|
||||
@@ -29,8 +37,56 @@ export const smsTemplate = writable<Models.SmsTemplate>({
|
||||
locale: null,
|
||||
message: null
|
||||
});
|
||||
|
||||
export const baseSmsTemplate = writable<Models.SmsTemplate>({
|
||||
type: null,
|
||||
locale: null,
|
||||
message: null
|
||||
});
|
||||
|
||||
export const templates = [
|
||||
{
|
||||
key: 'verification',
|
||||
title: 'Verification',
|
||||
description:
|
||||
'Send a verification email to users that sign in with their email and password.',
|
||||
component: EmailVerificationTemplate
|
||||
},
|
||||
{
|
||||
key: 'magicSession',
|
||||
title: 'Magic URL',
|
||||
description: 'Send an email to users that sign in with a magic URL.',
|
||||
component: EmailMagicUrlTemplate
|
||||
},
|
||||
{
|
||||
key: 'otpSession',
|
||||
title: 'OTP session',
|
||||
description: 'Send an email to users that sign in with a email OTP.',
|
||||
component: EmailMagicUrlTemplate
|
||||
},
|
||||
{
|
||||
key: 'recovery',
|
||||
title: 'Reset password',
|
||||
description: 'Send a recovery email to users that forget their password.',
|
||||
component: EmailRecoveryTemplate
|
||||
},
|
||||
{
|
||||
key: 'invitation',
|
||||
title: 'Invite user',
|
||||
description: 'Send an invitation email to become a member of your project.',
|
||||
component: EmailInviteTemplate
|
||||
},
|
||||
{
|
||||
key: 'mfaChallenge',
|
||||
title: '2FA verification',
|
||||
description: 'Send a two-factor authentication email to a user.',
|
||||
component: Email2FaTemplate
|
||||
},
|
||||
{
|
||||
key: 'sessionAlert',
|
||||
title: 'Session alert',
|
||||
description: 'Send an email to users when a new session is created.',
|
||||
component: EmailSessionAlertTemplate,
|
||||
hideDivider: true
|
||||
}
|
||||
];
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<script lang="ts">
|
||||
import { Layout, Skeleton } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let count: number = 5;
|
||||
export let textArea: boolean = true;
|
||||
</script>
|
||||
|
||||
<Layout.Stack inline gap="xl">
|
||||
{#each Array.from({ length: count }) as _}
|
||||
<Layout.Stack inline gap="xs">
|
||||
<Skeleton variant="line" width="25%" height={18} />
|
||||
<Skeleton variant="line" width="100%" height={35} />
|
||||
</Layout.Stack>
|
||||
{/each}
|
||||
|
||||
{#if textArea}
|
||||
<Layout.Stack inline gap="xs">
|
||||
<Skeleton variant="line" width="25%" height={18} />
|
||||
<Skeleton variant="line" width="100%" height={125} />
|
||||
</Layout.Stack>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
Reference in New Issue
Block a user