mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge branch 'feat-pink-v2' of github.com:appwrite/console into feat-v2-regions
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { Card, Tooltip } from '@appwrite.io/pink-svelte';
|
||||
import { Card, Tooltip, Icon } from '@appwrite.io/pink-svelte';
|
||||
import { type ComponentProps } from 'svelte';
|
||||
import type Selector from '@appwrite.io/pink-svelte/dist/card/Selector.svelte';
|
||||
|
||||
|
||||
@@ -32,6 +32,12 @@
|
||||
|
||||
let responseTab: 'logs' | 'errors' | 'headers' | 'body' = $state('logs');
|
||||
|
||||
let href = $derived(
|
||||
product === 'site'
|
||||
? 'https://appwrite.io/docs/products/sites/logs#log-details'
|
||||
: 'https://appwrite.io/docs/products/functions/develop#logging'
|
||||
);
|
||||
|
||||
onMount(() => {
|
||||
if (selectedLog?.errors) {
|
||||
responseTab = 'errors';
|
||||
@@ -128,8 +134,8 @@
|
||||
|
||||
<Input.Helper state="default">
|
||||
<span>
|
||||
Missing headers? Check the <Link variant="muted" href="#" external>docs</Link> to
|
||||
see the supported data and how to log it.
|
||||
Missing headers? Check the <Link variant="muted" {href} external>docs</Link> to see
|
||||
the supported data and how to log it.
|
||||
</span>
|
||||
</Input.Helper>
|
||||
{:else}
|
||||
@@ -146,12 +152,7 @@
|
||||
Body data is not captured by Appwrite for your user's security and privacy. To
|
||||
display body data in the Logs tab, use <InlineCode
|
||||
code="context.log()"
|
||||
size="s" />. <Link
|
||||
external
|
||||
href="https://appwrite.io/docs/products/functions/develop#logging"
|
||||
variant="muted">
|
||||
Learn more</Link
|
||||
>.
|
||||
size="s" />. <Link external {href} variant="muted">Learn more</Link>.
|
||||
</Typography.Text>
|
||||
</Card>
|
||||
{/if}
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
Button,
|
||||
Layout,
|
||||
Avatar,
|
||||
Typography
|
||||
Typography,
|
||||
Badge
|
||||
} from '@appwrite.io/pink-svelte';
|
||||
|
||||
import {
|
||||
@@ -77,7 +78,7 @@
|
||||
{ name: 'Functions', icon: IconLightningBolt, slug: 'functions', category: 'build' },
|
||||
{ name: 'Messaging', icon: IconChatBubble, slug: 'messaging', category: 'build' },
|
||||
{ name: 'Storage', icon: IconFolder, slug: 'storage', category: 'build' },
|
||||
{ name: 'Sites', icon: IconGlobeAlt, slug: 'sites', category: 'deploy' }
|
||||
{ name: 'Sites', icon: IconGlobeAlt, slug: 'sites', category: 'deploy', badge: 'New' }
|
||||
];
|
||||
</script>
|
||||
|
||||
@@ -208,14 +209,23 @@
|
||||
on:click={() => {
|
||||
trackEvent(`click_menu_${projectOption.slug}`);
|
||||
sideBarIsOpen = false;
|
||||
}}
|
||||
><span class="link-icon"
|
||||
><Icon icon={projectOption.icon} size="s" />
|
||||
</span><span
|
||||
}}>
|
||||
<span class="link-icon">
|
||||
<Icon icon={projectOption.icon} size="s" />
|
||||
</span>
|
||||
<span
|
||||
class:no-text={state === 'icons'}
|
||||
class:has-text={state === 'open'}
|
||||
class="link-text">{projectOption.name}</span
|
||||
></a>
|
||||
class="link-text">
|
||||
{projectOption.name}
|
||||
{#if projectOption?.badge}
|
||||
<Badge
|
||||
variant="secondary"
|
||||
content={projectOption.badge}
|
||||
size="s" />
|
||||
{/if}
|
||||
</span>
|
||||
</a>
|
||||
<span slot="tooltip">{projectOption.name}</span>
|
||||
</Tooltip>
|
||||
{/each}
|
||||
|
||||
@@ -101,6 +101,12 @@ export function secsToUnit(time: number, unit: Unit) {
|
||||
* @returns Formatted string like "3d 4h 30m 23s"
|
||||
*/
|
||||
export function formatTimeDetailed(time: number): string {
|
||||
if (typeof time !== 'number' || time === undefined || time === null) {
|
||||
return '-';
|
||||
}
|
||||
if (time <= 0) {
|
||||
return '0s';
|
||||
}
|
||||
const seconds = Math.floor(time % 60);
|
||||
const minutes = Math.floor((time / 60) % 60);
|
||||
const hours = Math.floor((time / (60 * 60)) % 24);
|
||||
|
||||
@@ -103,11 +103,13 @@
|
||||
Email templates <Badge variant="secondary" content="Experimental" />
|
||||
</svelte:fragment>
|
||||
Use templates to send and process account management emails.
|
||||
<Link.Anchor href="https://appwrite.io/docs/advanced/platform/message-templates">
|
||||
<Link.Anchor
|
||||
target="_blank"
|
||||
href="https://appwrite.io/docs/advanced/platform/message-templates">
|
||||
Learn more
|
||||
</Link.Anchor>
|
||||
<svelte:fragment slot="aside">
|
||||
<Layout.Stack>
|
||||
<Layout.Stack gap="none">
|
||||
<Accordion
|
||||
title="Verification"
|
||||
bind:open={emailVerificationOpen}
|
||||
@@ -127,8 +129,12 @@
|
||||
e.preventDefault();
|
||||
openEmail('magicSession');
|
||||
}}>
|
||||
Send an email to users that sign in with a magic URL.
|
||||
<EmailMagicUrlTemplate />
|
||||
<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"
|
||||
@@ -137,8 +143,11 @@
|
||||
e.preventDefault();
|
||||
openEmail('otpSession');
|
||||
}}>
|
||||
Send an email to users that sign in with a email OTP.
|
||||
<EmailMagicUrlTemplate />
|
||||
<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"
|
||||
@@ -147,8 +156,10 @@
|
||||
e.preventDefault();
|
||||
openEmail('recovery');
|
||||
}}>
|
||||
Send a recovery email to users that forget their password.
|
||||
<EmailRecoveryTemplate />
|
||||
<Layout.Stack>
|
||||
<Typography.Text>
|
||||
Send a recovery email to users that forget their password.</Typography.Text>
|
||||
<EmailRecoveryTemplate /></Layout.Stack>
|
||||
</Accordion>
|
||||
<Accordion
|
||||
title="Invite user"
|
||||
@@ -157,8 +168,11 @@
|
||||
e.preventDefault();
|
||||
openEmail('invitation');
|
||||
}}>
|
||||
Send an invitation email to become a member of your project.
|
||||
<EmailInviteTemplate />
|
||||
<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"
|
||||
@@ -167,8 +181,10 @@
|
||||
e.preventDefault();
|
||||
openEmail('mfaChallenge');
|
||||
}}>
|
||||
Send a two-factor authentication email to a user.
|
||||
<Email2FaTemplate />
|
||||
<Layout.Stack>
|
||||
<Typography.Text>
|
||||
Send a two-factor authentication email to a user.</Typography.Text>
|
||||
<Email2FaTemplate /></Layout.Stack>
|
||||
</Accordion>
|
||||
<Accordion
|
||||
title="Session alert"
|
||||
@@ -177,8 +193,10 @@
|
||||
e.preventDefault();
|
||||
openEmail('sessionAlert');
|
||||
}}>
|
||||
Send an email to users when a new session is created.
|
||||
<EmailSessionAlertTemplate />
|
||||
<Layout.Stack>
|
||||
<Typography.Text>
|
||||
Send an email to users when a new session is created.</Typography.Text>
|
||||
<EmailSessionAlertTemplate /></Layout.Stack>
|
||||
</Accordion>
|
||||
</Layout.Stack>
|
||||
</svelte:fragment>
|
||||
|
||||
+11
-9
@@ -7,7 +7,7 @@
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { Id } from '$lib/components';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Layout } from '@appwrite.io/pink-svelte';
|
||||
import { Layout, Card } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
let locale = 'en';
|
||||
@@ -35,11 +35,13 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{otp}}'}>{'{{otp}}'}</Id>
|
||||
</EmailTemplate>
|
||||
</Layout.Stack>
|
||||
<Card.Base variant="secondary" padding="s">
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{otp}}'}>{'{{otp}}'}</Id>
|
||||
</EmailTemplate>
|
||||
</Layout.Stack>
|
||||
</Card.Base>
|
||||
|
||||
+12
-10
@@ -7,7 +7,7 @@
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { Id } from '$lib/components';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Layout } from '@appwrite.io/pink-svelte';
|
||||
import { Layout, Card } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
let locale = 'en';
|
||||
@@ -35,12 +35,14 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<Id value={'{{team}}'}>{'{{team}}'}</Id>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{redirect}}'}>{'{{redirect}}'}</Id>
|
||||
</EmailTemplate>
|
||||
</Layout.Stack>
|
||||
<Card.Base variant="secondary" padding="s">
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<Id value={'{{team}}'}>{'{{team}}'}</Id>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{redirect}}'}>{'{{redirect}}'}</Id>
|
||||
</EmailTemplate>
|
||||
</Layout.Stack>
|
||||
</Card.Base>
|
||||
|
||||
+11
-9
@@ -7,7 +7,7 @@
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { Id } from '$lib/components';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Layout } from '@appwrite.io/pink-svelte';
|
||||
import { Layout, Card } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
|
||||
@@ -37,11 +37,13 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{redirect}}'}>{'{{redirect}}'}</Id>
|
||||
</EmailTemplate>
|
||||
</Layout.Stack>
|
||||
<Card.Base variant="secondary" padding="s">
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{redirect}}'}>{'{{redirect}}'}</Id>
|
||||
</EmailTemplate>
|
||||
</Layout.Stack>
|
||||
</Card.Base>
|
||||
|
||||
+11
-9
@@ -7,7 +7,7 @@
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { Id } from '$lib/components';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Layout } from '@appwrite.io/pink-svelte';
|
||||
import { Layout, Card } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
|
||||
@@ -36,11 +36,13 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{redirect}}'}>{'{{redirect}}'}</Id>
|
||||
</EmailTemplate>
|
||||
</Layout.Stack>
|
||||
<Card.Base variant="secondary" padding="s">
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{redirect}}'}>{'{{redirect}}'}</Id>
|
||||
</EmailTemplate>
|
||||
</Layout.Stack>
|
||||
</Card.Base>
|
||||
|
||||
+13
-11
@@ -7,7 +7,7 @@
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { Id } from '$lib/components';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Layout } from '@appwrite.io/pink-svelte';
|
||||
import { Layout, Card } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
let locale = 'en';
|
||||
@@ -35,13 +35,15 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{device}}'}>{'{{device}}'}</Id>
|
||||
<Id value={'{{ipAddress'}>{'{{ipAddress}}'}</Id>
|
||||
<Id value={'{{country'}>{'{{country}}'}</Id>
|
||||
</EmailTemplate>
|
||||
</Layout.Stack>
|
||||
<Card.Base variant="secondary" padding="s">
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{device}}'}>{'{{device}}'}</Id>
|
||||
<Id value={'{{ipAddress'}>{'{{ipAddress}}'}</Id>
|
||||
<Id value={'{{country'}>{'{{country}}'}</Id>
|
||||
</EmailTemplate>
|
||||
</Layout.Stack>
|
||||
</Card.Base>
|
||||
|
||||
+66
-68
@@ -83,74 +83,72 @@
|
||||
$: isSmtpEnabled = $project?.smtpEnabled;
|
||||
</script>
|
||||
|
||||
<Card.Base variant="secondary" padding="s">
|
||||
{#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' : ''}>
|
||||
<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" />
|
||||
|
||||
<InputTextarea
|
||||
bind:value={$emailTemplate.message}
|
||||
id="message"
|
||||
label="Message"
|
||||
placeholder="Enter your message"
|
||||
readonly={!isSmtpEnabled}>
|
||||
<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>
|
||||
</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">
|
||||
<Button on:click={() => (openResetModal = true)} text>Reset changes</Button>
|
||||
<Button submit disabled={isButtonDisabled}>Update</Button>
|
||||
</div>
|
||||
</Form>
|
||||
{#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>
|
||||
</Card.Base>
|
||||
{/if}
|
||||
<div class:u-opacity-0={loading} style={loading ? '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" />
|
||||
|
||||
<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>
|
||||
</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">
|
||||
<Button on:click={() => (openResetModal = true)} text>Reset changes</Button>
|
||||
<Button submit disabled={isButtonDisabled}>Update</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
<ResetEmail bind:show={openResetModal} />
|
||||
|
||||
+11
-9
@@ -7,7 +7,7 @@
|
||||
import { Id } from '$lib/components';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Layout } from '@appwrite.io/pink-svelte';
|
||||
import { Layout, Card } from '@appwrite.io/pink-svelte';
|
||||
|
||||
const projectId = page.params.project;
|
||||
|
||||
@@ -36,11 +36,13 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Layout.Stack>
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{redirect}}'}>{'{{redirect}}'}</Id>
|
||||
</EmailTemplate>
|
||||
</Layout.Stack>
|
||||
<Card.Base variant="secondary" padding="s">
|
||||
<Layout.Stack gap="l">
|
||||
<LocaleOptions on:change={onLocaleChange} bind:value={locale} />
|
||||
<EmailTemplate bind:loading>
|
||||
<Id value={'{{user}}'}>{'{{user}}'}</Id>
|
||||
<Id value={'{{project}}'}>{'{{project}}'}</Id>
|
||||
<Id value={'{{redirect}}'}>{'{{redirect}}'}</Id>
|
||||
</EmailTemplate>
|
||||
</Layout.Stack>
|
||||
</Card.Base>
|
||||
|
||||
+10
-12
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { Card, Input } from '@appwrite.io/pink-svelte';
|
||||
import { Input } from '@appwrite.io/pink-svelte';
|
||||
import { localeCodes } from './store';
|
||||
|
||||
export let value = 'en';
|
||||
@@ -10,14 +10,12 @@
|
||||
}));
|
||||
</script>
|
||||
|
||||
<Card.Base variant="secondary" padding="s">
|
||||
<Input.ComboBox
|
||||
label="Template language"
|
||||
on:change
|
||||
id="language"
|
||||
placeholder="Select a language"
|
||||
name="locale"
|
||||
bind:value
|
||||
required
|
||||
{options} />
|
||||
</Card.Base>
|
||||
<Input.ComboBox
|
||||
label="Template language"
|
||||
on:change
|
||||
id="language"
|
||||
placeholder="Select a language"
|
||||
name="locale"
|
||||
bind:value
|
||||
required
|
||||
{options} />
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import { project } from '../../store';
|
||||
import { loadEmailTemplate } from './+page.svelte';
|
||||
import { baseEmailTemplate, emailTemplate } from './store';
|
||||
import { Dialog, Layout, Alert } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let show = false;
|
||||
|
||||
@@ -44,15 +45,24 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal onSubmit={reset} {error} bind:show>
|
||||
<Dialog bind:open={show} title="Reset changes">
|
||||
<svelte:fragment slot="title">Reset email template?</svelte:fragment>
|
||||
|
||||
<Layout.Stack>
|
||||
<p class="text">
|
||||
Are you sure you want to reset the email template?
|
||||
<b>Default values will be set in all inputs.</b>
|
||||
</p>
|
||||
|
||||
{#if error}
|
||||
<Alert.Inline status="warning">{error}</Alert.Inline>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
|
||||
<svelte:fragment slot="footer">
|
||||
<Button text secondary on:click={() => (show = false)}>Cancel</Button>
|
||||
<Button secondary submit>Reset</Button>
|
||||
<Layout.Stack direction="row" gap="s" justifyContent="flex-end">
|
||||
<Button text secondary on:click={() => (show = false)}>Cancel</Button>
|
||||
<Button on:click={reset}>Reset</Button>
|
||||
</Layout.Stack>
|
||||
</svelte:fragment>
|
||||
</Modal>
|
||||
</Dialog>
|
||||
|
||||
+1
-1
@@ -324,7 +324,7 @@
|
||||
variant="secondary"
|
||||
padding="s"
|
||||
--input-background-color="var(--bgcolor-neutral-primary)">
|
||||
<div class="modal-form">
|
||||
<div>
|
||||
<div class="u-flex-vertical u-gap-24">
|
||||
<div class="u-flex-vertical u-gap-4">
|
||||
<Layout.Grid columns={4}>
|
||||
|
||||
+3
-1
@@ -127,7 +127,9 @@
|
||||
|
||||
<Modal title="Create Git deployment" bind:show onSubmit={createDeployment} bind:error>
|
||||
<span slot="description">
|
||||
Enter a valid commit reference to create a new deployment. <Link href="#">Learn more</Link>
|
||||
Enter a valid commit reference to create a new deployment. <Link
|
||||
href="https://appwrite.io/docs/products/functions/deployments#create-deployment"
|
||||
external>Learn more</Link>
|
||||
</span>
|
||||
{#if hasRepository}
|
||||
{#await load()}
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import { Dependencies } from '$lib/constants.js';
|
||||
import { isCloud } from '$lib/system';
|
||||
import type { Domain, DomainsList } from '$lib/sdk/domains.js';
|
||||
|
||||
export const load = async ({ parent, depends, params }) => {
|
||||
export const load = async ({ depends, params }) => {
|
||||
depends(Dependencies.DOMAINS);
|
||||
|
||||
let domain: Domain;
|
||||
|
||||
+1
-1
@@ -33,5 +33,5 @@
|
||||
</script>
|
||||
|
||||
<Confirm onSubmit={deleteProvider} title="Delete provider" bind:open={showDelete} bind:error>
|
||||
Are you sure you want to delete <b>{$provider.name}</b> from '{$project.name}'?
|
||||
<span>Are you sure you want to delete <b>{$provider.name}</b> from '{$project.name}'?</span>
|
||||
</Confirm>
|
||||
|
||||
+4
-3
@@ -13,6 +13,7 @@
|
||||
import { Typography } from '@appwrite.io/pink-svelte';
|
||||
import { getProviderText } from '../../helper';
|
||||
import { page } from '$app/state';
|
||||
import { Layout } from '@appwrite.io/pink-svelte';
|
||||
|
||||
let enabled: boolean = null;
|
||||
|
||||
@@ -132,9 +133,9 @@
|
||||
bind:value={enabled} />
|
||||
</ul>
|
||||
<div>
|
||||
<p class="title">
|
||||
Provider: <Provider noIcon provider={$providerData.provider} />
|
||||
</p>
|
||||
<Layout.Stack direction="row" gap="xs">
|
||||
<span>Provider:</span><Provider noIcon provider={$providerData.provider} />
|
||||
</Layout.Stack>
|
||||
<p class="title">Type: {getProviderText($providerData.type)}</p>
|
||||
<p>Created: {toLocaleDateTime($providerData.$createdAt)}</p>
|
||||
</div>
|
||||
|
||||
+38
-8
@@ -25,8 +25,12 @@
|
||||
APNSProviderParams
|
||||
} from './store';
|
||||
import TooltipPopover from './tooltipPopover.svelte';
|
||||
import { Icon, Tooltip, Upload, Layout, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
|
||||
import { removeFile } from '$lib/helpers/files';
|
||||
|
||||
export let files: Record<string, FileList>;
|
||||
|
||||
export let input: ProviderInput;
|
||||
export let params: Partial<
|
||||
| TwilioProviderParams
|
||||
@@ -100,14 +104,40 @@
|
||||
<TooltipPopover slot="info" {popover} {popoverProps} tooltip={input.tooltip} />
|
||||
</InputPhone>
|
||||
{:else if input.type === 'file'}
|
||||
<InputFile
|
||||
label={input.label}
|
||||
allowedFileExtensions={input.allowedFileExtensions}
|
||||
required={!input.optional}
|
||||
tooltip={input.tooltip}
|
||||
{popover}
|
||||
{popoverProps}
|
||||
bind:files={files[input.name]} />
|
||||
<Upload.Dropzone
|
||||
extensions={['json']}
|
||||
bind:files={files[input.name]}
|
||||
required={!input.optional}>
|
||||
<Layout.Stack alignItems="center" gap="s">
|
||||
<Layout.Stack alignItems="center" gap="s">
|
||||
<Layout.Stack alignItems="center" justifyContent="center" direction="row" gap="s">
|
||||
<Typography.Text variant="l-500">
|
||||
Drag and drop service account JSON here or click to upload
|
||||
</Typography.Text>
|
||||
<Tooltip>
|
||||
<Layout.Stack alignItems="center" justifyContent="center" inline>
|
||||
<Icon icon={IconInfo} size="s" />
|
||||
</Layout.Stack>
|
||||
<svelte:fragment slot="tooltip">Only .json files allowed</svelte:fragment>
|
||||
</Tooltip>
|
||||
</Layout.Stack>
|
||||
<Typography.Caption variant="400">Max file size 10MB</Typography.Caption>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</Upload.Dropzone>
|
||||
{#if files[input.name]?.length}
|
||||
<Upload.List
|
||||
bind:files={files[input.name]}
|
||||
on:remove={(e) => (files[input.name] = removeFile(e.detail, files[input.name]))} />
|
||||
{/if}
|
||||
<!-- <InputFile-->
|
||||
<!-- label={input.label}-->
|
||||
<!-- allowedFileExtensions={input.allowedFileExtensions}-->
|
||||
<!-- required={!input.optional}-->
|
||||
<!-- tooltip={input.tooltip}-->
|
||||
<!-- {popover}-->
|
||||
<!-- {popoverProps}-->
|
||||
<!-- bind:files={files[input.name]} />-->
|
||||
{:else if input.type === 'switch'}
|
||||
<InputSwitch label={input.label} id={input.name} bind:value={params[input.name]}>
|
||||
<svelte:fragment slot="description">
|
||||
|
||||
+8
-3
@@ -12,6 +12,14 @@
|
||||
let showCustomId = false;
|
||||
let id: string = null;
|
||||
|
||||
$: {
|
||||
name;
|
||||
id;
|
||||
$provider;
|
||||
|
||||
beforeSubmit();
|
||||
}
|
||||
|
||||
async function beforeSubmit() {
|
||||
switch ($provider) {
|
||||
case Providers.Twilio:
|
||||
@@ -133,9 +141,6 @@
|
||||
</script>
|
||||
|
||||
<WizardStep {beforeSubmit}>
|
||||
<svelte:fragment slot="title">Provider</svelte:fragment>
|
||||
<div class="u-sep-block-start u-padding-block-end-32"></div>
|
||||
|
||||
<InputText
|
||||
id="name"
|
||||
label="Name"
|
||||
|
||||
+16
-3
@@ -16,9 +16,16 @@
|
||||
import { getProviderText } from '../../helper';
|
||||
|
||||
let files: Record<string, FileList> = {};
|
||||
const inputs = providers[$providerType].providers[$provider].configure;
|
||||
$: inputs = providers[$providerType].providers[$provider].configure;
|
||||
let open = false;
|
||||
|
||||
$: {
|
||||
files;
|
||||
$providerType;
|
||||
$provider;
|
||||
|
||||
beforeSubmit();
|
||||
}
|
||||
onMount(() => {
|
||||
const flattened = [];
|
||||
for (const i of inputs) {
|
||||
@@ -29,7 +36,11 @@
|
||||
}
|
||||
}
|
||||
for (const input of flattened) {
|
||||
if (input.type === 'file' && $providerParams[$provider][input.name].length > 0) {
|
||||
if (
|
||||
input.type === 'file' &&
|
||||
$providerParams[$provider] &&
|
||||
$providerParams[$provider][input.name].length > 0
|
||||
) {
|
||||
const dataTransfer = new DataTransfer();
|
||||
const f = new File(
|
||||
[$providerParams[$provider][input.name]],
|
||||
@@ -138,7 +149,9 @@
|
||||
</div>
|
||||
</WizardStep>
|
||||
|
||||
<CreateMember bind:showCreate={$newMemberModal} />
|
||||
{#if $newMemberModal}
|
||||
<CreateMember bind:showCreate={$newMemberModal} />
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
.need-a-hand {
|
||||
|
||||
@@ -5,18 +5,21 @@
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import Container from '$lib/layout/container.svelte';
|
||||
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
|
||||
import { Card, Empty, Icon, Layout } from '@appwrite.io/pink-svelte';
|
||||
import SearchQuery from '$lib/components/searchQuery.svelte';
|
||||
import { Card, Empty, Icon } from '@appwrite.io/pink-svelte';
|
||||
import { app } from '$lib/stores/app';
|
||||
import { Click, trackEvent } from '$lib/actions/analytics';
|
||||
import Table from './table.svelte';
|
||||
import { ResponsiveContainerHeader } from '$lib/layout';
|
||||
|
||||
let { data } = $props();
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
<Layout.Stack direction="row" justifyContent="space-between">
|
||||
<SearchQuery placeholder="Search domain" />
|
||||
<ResponsiveContainerHeader
|
||||
hasSearch
|
||||
hideView
|
||||
searchPlaceholder="Search by domain"
|
||||
analyticsSource="settings_domain_overview">
|
||||
<Button
|
||||
href={`${base}/project-${page.params.region}-${page.params.project}/settings/domains/add-domain`}
|
||||
on:click={() => {
|
||||
@@ -27,8 +30,7 @@
|
||||
<Icon icon={IconPlus} size="s" />
|
||||
Add domain
|
||||
</Button>
|
||||
</Layout.Stack>
|
||||
|
||||
</ResponsiveContainerHeader>
|
||||
{#if data.rules.total}
|
||||
<Table domains={data.rules} />
|
||||
|
||||
|
||||
+15
-24
@@ -5,21 +5,27 @@
|
||||
import { Wizard } from '$lib/layout';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Fieldset, Layout } from '@appwrite.io/pink-svelte';
|
||||
import { Fieldset } from '@appwrite.io/pink-svelte';
|
||||
import { goto, invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { writable } from 'svelte/store';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
const routeBase = `${base}/project-${page.params.region}-${page.params.project}/settings/domains`;
|
||||
|
||||
//TODO: enable once combo box is fixed
|
||||
// let { data } = $props();
|
||||
|
||||
let formComponent: Form;
|
||||
let isSubmitting = $state(writable(false));
|
||||
|
||||
let showConnectRepo = $state(false);
|
||||
let domainName = $state('');
|
||||
|
||||
onMount(() => {
|
||||
if (page.url.searchParams.has('domain')) {
|
||||
domainName = page.url.searchParams.get('domain');
|
||||
}
|
||||
});
|
||||
|
||||
async function addDomain() {
|
||||
try {
|
||||
const rule = await sdk
|
||||
@@ -43,27 +49,12 @@
|
||||
|
||||
<Wizard title="Add domain" href={routeBase} column columnSize="s" confirmExit>
|
||||
<Form bind:this={formComponent} onSubmit={addDomain} bind:isSubmitting>
|
||||
<Layout.Stack gap="xxl">
|
||||
<Fieldset legend="Domain">
|
||||
<!-- <Input.ComboBox
|
||||
label="Domain"
|
||||
id="domain"
|
||||
name="domain"
|
||||
bind:value={domain}
|
||||
options={data.domains.rules.map((domain) => ({
|
||||
label: domain.domain,
|
||||
value: domain.domain
|
||||
}))}
|
||||
required
|
||||
placeholder="appwrite.example.com" /> -->
|
||||
<InputDomain
|
||||
label="Domain"
|
||||
id="domain"
|
||||
bind:value={domainName}
|
||||
required
|
||||
placeholder="appwrite.example.com" />
|
||||
</Fieldset>
|
||||
</Layout.Stack>
|
||||
<InputDomain
|
||||
label="Domain"
|
||||
id="domain"
|
||||
bind:value={domainName}
|
||||
required
|
||||
placeholder="appwrite.example.com" />
|
||||
</Form>
|
||||
|
||||
<svelte:fragment slot="footer">
|
||||
|
||||
+75
-11
@@ -1,7 +1,14 @@
|
||||
<script lang="ts">
|
||||
import { IconGlobeAlt } from '@appwrite.io/pink-icons-svelte';
|
||||
import { Card, Divider, Icon, Layout, Typography } from '@appwrite.io/pink-svelte';
|
||||
import VerificationFieldset from './verificationFieldset.svelte';
|
||||
import {
|
||||
Card,
|
||||
Divider,
|
||||
Fieldset,
|
||||
Icon,
|
||||
Layout,
|
||||
Tabs,
|
||||
Typography
|
||||
} from '@appwrite.io/pink-svelte';
|
||||
import { Button, Form } from '$lib/elements/forms';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
@@ -13,21 +20,34 @@
|
||||
import Wizard from '$lib/layout/wizard.svelte';
|
||||
import { base } from '$app/paths';
|
||||
import { writable } from 'svelte/store';
|
||||
import { consoleVariables } from '$routes/(console)/store';
|
||||
import NameserverTable from '$lib/components/domains/nameserverTable.svelte';
|
||||
import RecordTable from '$lib/components/domains/recordTable.svelte';
|
||||
|
||||
let { data } = $props();
|
||||
|
||||
const ruleId = page.url.searchParams.get('rule');
|
||||
const routeBase = `${base}/project-${page.params.region}-${page.params.project}/settings/domains`;
|
||||
let selectedTab: 'cname' | 'nameserver' = $state();
|
||||
let isSubDomain = $derived(page.params.domain?.split('.')?.length >= 3);
|
||||
|
||||
let selectedTab: 'cname' | 'nameserver' | 'a' | 'aaaa' = $state(
|
||||
!!$consoleVariables._APP_DOMAIN_TARGET_CNAME && isSubDomain
|
||||
? 'cname'
|
||||
: !!$consoleVariables._APP_DOMAIN_TARGET_A
|
||||
? 'a'
|
||||
: !!$consoleVariables._APP_DOMAIN_TARGET_AAAA
|
||||
? 'aaaa'
|
||||
: 'nameserver'
|
||||
);
|
||||
let verified = $state(false);
|
||||
|
||||
let routeBase = `${base}/project-${page.params.region}-${page.params.project}/settings/domains`;
|
||||
let isSubmitting = $state(writable(false));
|
||||
|
||||
async function verify() {
|
||||
const isNewDomain =
|
||||
data.domainsList.domains.findIndex((rule) => rule.domain === page.params.domain) === -1;
|
||||
try {
|
||||
if (selectedTab === 'cname') {
|
||||
if (selectedTab !== 'nameserver') {
|
||||
const ruleData = await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.proxy.updateRuleVerification(ruleId);
|
||||
@@ -46,9 +66,9 @@
|
||||
});
|
||||
await goto(routeBase);
|
||||
await invalidate(Dependencies.DOMAINS);
|
||||
await invalidate(Dependencies.SITES_DOMAINS);
|
||||
} catch (error) {
|
||||
verified = false;
|
||||
isSubmitting.set(false);
|
||||
addNotification({
|
||||
type: 'error',
|
||||
message: error.message
|
||||
@@ -84,14 +104,58 @@
|
||||
</Layout.Stack>
|
||||
</Card.Base>
|
||||
|
||||
<VerificationFieldset domain={page.params.domain} {verified} bind:selectedTab>
|
||||
<Divider />
|
||||
<Layout.Stack direction="row" justifyContent="flex-end">
|
||||
<Fieldset legend="Verification">
|
||||
<Layout.Stack gap="xl">
|
||||
<div>
|
||||
<Button submit disabled={$isSubmitting}>Verify</Button>
|
||||
<Tabs.Root variant="secondary" let:root>
|
||||
{#if isSubDomain && !!$consoleVariables._APP_DOMAIN_TARGET_CNAME && $consoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost'}
|
||||
<Tabs.Item.Button
|
||||
{root}
|
||||
on:click={() => (selectedTab = 'cname')}
|
||||
active={selectedTab === 'cname'}>
|
||||
CNAME
|
||||
</Tabs.Item.Button>
|
||||
{/if}
|
||||
{#if isCloud}
|
||||
<Tabs.Item.Button
|
||||
{root}
|
||||
on:click={() => (selectedTab = 'nameserver')}
|
||||
active={selectedTab === 'nameserver'}>
|
||||
Nameservers
|
||||
</Tabs.Item.Button>
|
||||
{/if}
|
||||
{#if !!$consoleVariables._APP_DOMAIN_TARGET_A && $consoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1'}
|
||||
<Tabs.Item.Button
|
||||
{root}
|
||||
on:click={() => (selectedTab = 'a')}
|
||||
active={selectedTab === 'a'}>
|
||||
A
|
||||
</Tabs.Item.Button>
|
||||
{/if}
|
||||
{#if !!$consoleVariables._APP_DOMAIN_TARGET_AAAA && $consoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1'}
|
||||
<Tabs.Item.Button
|
||||
{root}
|
||||
on:click={() => (selectedTab = 'aaaa')}
|
||||
active={selectedTab === 'aaaa'}>
|
||||
AAAA
|
||||
</Tabs.Item.Button>
|
||||
{/if}
|
||||
</Tabs.Root>
|
||||
<Divider />
|
||||
</div>
|
||||
{#if selectedTab === 'nameserver'}
|
||||
<NameserverTable domain={page.params.domain} {verified} />
|
||||
{:else}
|
||||
<RecordTable domain={page.params.domain} {verified} variant={selectedTab} />
|
||||
{/if}
|
||||
<Divider />
|
||||
<Layout.Stack direction="row" justifyContent="flex-end">
|
||||
<div>
|
||||
<Button submit disabled={$isSubmitting}>Verify</Button>
|
||||
</div>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
</VerificationFieldset>
|
||||
</Fieldset>
|
||||
</Layout.Stack>
|
||||
</Form>
|
||||
</Wizard>
|
||||
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
<script lang="ts">
|
||||
import CnameTable from '$lib/components/domains/cnameTable.svelte';
|
||||
import NameserverTable from '$lib/components/domains/nameserverTable.svelte';
|
||||
import { isCloud, isSelfHosted } from '$lib/system';
|
||||
import { Divider, Fieldset, Layout, Tabs } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let domain: string;
|
||||
export let verified: boolean;
|
||||
|
||||
$: isSubDomain = domain?.split('.')?.length >= 3;
|
||||
export let selectedTab: 'cname' | 'nameserver' =
|
||||
isSubDomain || isSelfHosted ? 'cname' : 'nameserver';
|
||||
</script>
|
||||
|
||||
<Fieldset legend="Verification">
|
||||
<Layout.Stack gap="xl">
|
||||
<div>
|
||||
<Tabs.Root variant="secondary" let:root>
|
||||
{#if isSubDomain}
|
||||
<Tabs.Item.Button
|
||||
{root}
|
||||
on:click={() => (selectedTab = 'cname')}
|
||||
active={selectedTab === 'cname'}>
|
||||
CNAME
|
||||
</Tabs.Item.Button>
|
||||
{/if}
|
||||
{#if isCloud}
|
||||
<Tabs.Item.Button
|
||||
{root}
|
||||
on:click={() => (selectedTab = 'nameserver')}
|
||||
active={selectedTab === 'nameserver'}>
|
||||
Nameservers
|
||||
</Tabs.Item.Button>
|
||||
{/if}
|
||||
</Tabs.Root>
|
||||
<Divider />
|
||||
</div>
|
||||
{#if selectedTab === 'cname' && isSubDomain}
|
||||
<CnameTable {domain} {verified} />
|
||||
{:else if isCloud}
|
||||
<NameserverTable {domain} {verified} />
|
||||
{/if}
|
||||
<slot />
|
||||
</Layout.Stack>
|
||||
</Fieldset>
|
||||
+2
-6
@@ -24,7 +24,7 @@
|
||||
await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.proxy.deleteRule(selectedDomain.$id);
|
||||
await invalidate(Dependencies.SITES_DOMAINS);
|
||||
await invalidate(Dependencies.DOMAINS);
|
||||
show = false;
|
||||
addNotification({
|
||||
type: 'success',
|
||||
@@ -41,11 +41,7 @@
|
||||
<Confirm title="Delete domain" bind:open={show} onSubmit={deleteDomain} bind:error confirmDeletion>
|
||||
{#if selectedDomain}
|
||||
<Typography.Text variant="m-400">
|
||||
Are you sure you want to delete this domain? You will no longer be able to view your
|
||||
site by visiting:
|
||||
</Typography.Text>
|
||||
<Typography.Text variant="m-500">
|
||||
{selectedDomain.domain}
|
||||
Are you sure you want to delete this domain?
|
||||
</Typography.Text>
|
||||
{/if}
|
||||
</Confirm>
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
await sdk
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.proxy.updateRuleVerification(selectedDomain.$id);
|
||||
await invalidate(Dependencies.SITES_DOMAINS);
|
||||
await invalidate(Dependencies.DOMAINS);
|
||||
show = false;
|
||||
addNotification({
|
||||
type: 'success',
|
||||
|
||||
@@ -5,7 +5,15 @@
|
||||
import { protocol } from '$routes/(console)/store';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { IconDotsHorizontal, IconRefresh, IconTrash } from '@appwrite.io/pink-icons-svelte';
|
||||
import { ActionMenu, Icon, Layout, Popover, Table, Typography } from '@appwrite.io/pink-svelte';
|
||||
import {
|
||||
ActionMenu,
|
||||
Badge,
|
||||
Icon,
|
||||
Layout,
|
||||
Popover,
|
||||
Table,
|
||||
Typography
|
||||
} from '@appwrite.io/pink-svelte';
|
||||
import DeleteDomainModal from './deleteDomainModal.svelte';
|
||||
import RetryDomainModal from './retryDomainModal.svelte';
|
||||
import { columns } from './store';
|
||||
@@ -19,7 +27,6 @@
|
||||
let showDelete = $state(false);
|
||||
let showRetry = $state(false);
|
||||
let selectedDomain: Models.ProxyRule = $state(null);
|
||||
let showPreviewDomainModal = $state(false);
|
||||
</script>
|
||||
|
||||
<Table.Root columns={[...$columns, { id: 'actions', width: 40 }]} let:root>
|
||||
@@ -39,14 +46,15 @@
|
||||
<Link external href={`${$protocol}${domain.domain}`} variant="quiet" icon>
|
||||
<Typography.Text truncate>
|
||||
{domain.domain}
|
||||
{#if domain.status !== 'verified'}
|
||||
<Badge
|
||||
variant="secondary"
|
||||
type="error"
|
||||
content="Verification failed"
|
||||
size="s" />
|
||||
{/if}
|
||||
</Typography.Text>
|
||||
</Link>
|
||||
{:else if column.id === 'redirectUrl'}
|
||||
<!-- TODO design redirect status code -->
|
||||
{domain?.redirectUrl || 'No redirect'}
|
||||
{domain?.redirectStatusCode ? `(${domain.redirectStatusCode})` : ''}
|
||||
{:else if column.id === 'deploymentVcsProviderBranch'}
|
||||
{domain.deploymentVcsProviderBranch || '-'}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{/each}
|
||||
@@ -69,7 +77,6 @@
|
||||
<ActionMenu.Item.Button
|
||||
leadingIcon={IconRefresh}
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
selectedDomain = domain;
|
||||
showRetry = true;
|
||||
toggle(e);
|
||||
@@ -81,12 +88,11 @@
|
||||
status="danger"
|
||||
leadingIcon={IconTrash}
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
selectedDomain = domain;
|
||||
showDelete = true;
|
||||
toggle(e);
|
||||
trackEvent(Click.DomainDeleteClick, {
|
||||
source: 'sites_domain_overview'
|
||||
source: 'settings_domain_overview'
|
||||
});
|
||||
}}>
|
||||
Delete
|
||||
|
||||
+5
-1
@@ -122,7 +122,11 @@
|
||||
{#if secretVariables?.length > 0}
|
||||
<Alert.Inline status="info">
|
||||
{secretVariables.length} secret variables are hidden from the editor. Their values will
|
||||
remain unchanged. <Link href="#" variant="muted">Learn more</Link>.
|
||||
remain unchanged. <Link
|
||||
href="https://appwrite.io/docs/products/sites/develop#accessing-environment-variables"
|
||||
external
|
||||
variant="muted">Learn more</Link
|
||||
>.
|
||||
</Alert.Inline>
|
||||
{/if}
|
||||
<Layout.Stack gap="s">
|
||||
|
||||
+3
-1
@@ -132,7 +132,9 @@
|
||||
|
||||
<Modal title="Create Git deployment" bind:show onSubmit={createDeployment} bind:error>
|
||||
<span slot="description">
|
||||
Enter a valid commit reference to create a new deployment. <Link href="#">Learn more</Link>
|
||||
Enter a valid commit reference to create a new deployment. <Link
|
||||
href="https://appwrite.io/docs/products/sites/deployments#create-deployment"
|
||||
external>Learn more</Link>
|
||||
</span>
|
||||
{#if hasRepository}
|
||||
{#await load()}
|
||||
|
||||
+20
-4
@@ -7,6 +7,8 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/state';
|
||||
import { UsageCard } from '$lib/components';
|
||||
import { humanFileSize } from '$lib/helpers/sizeConvertion';
|
||||
import { formatTimeDetailed } from '$lib/helpers/timeConversion';
|
||||
|
||||
const now = new Date();
|
||||
const rangeOptions = [
|
||||
@@ -33,17 +35,17 @@
|
||||
description: 'Total builds time'
|
||||
},
|
||||
{
|
||||
id: 'avgTime',
|
||||
id: 'buildsTimeAverage',
|
||||
value: null,
|
||||
description: 'Avg. builds time'
|
||||
},
|
||||
{
|
||||
id: 'success',
|
||||
id: 'buildsSuccessTotal',
|
||||
value: null,
|
||||
description: 'Successful'
|
||||
},
|
||||
{
|
||||
id: 'failed',
|
||||
id: 'buildsFailedTotal',
|
||||
value: null,
|
||||
description: 'Failed '
|
||||
}
|
||||
@@ -65,7 +67,21 @@
|
||||
.forProject(page.params.region, page.params.project)
|
||||
.sites.getUsage(page.params.site, range);
|
||||
metrics = metrics.map((metric) => {
|
||||
metric.value = usage[metric.id] ?? '-';
|
||||
if (metric.id === 'buildsStorageTotal') {
|
||||
const size = humanFileSize(usage[metric.id]);
|
||||
|
||||
metric.value = parseInt(size?.value) > 0 ? size.value + size.unit : '-';
|
||||
} else if (
|
||||
metric.id === 'buildsTimeTotal' ||
|
||||
metric.id === 'buildsTimeAverage'
|
||||
) {
|
||||
const seconds = usage[metric.id] > 0 ? usage[metric.id] / 1000 : 0;
|
||||
const time = formatTimeDetailed(seconds);
|
||||
|
||||
metric.value = time !== '0s' ? time : '-';
|
||||
} else {
|
||||
metric.value = usage[metric.id] ?? '-';
|
||||
}
|
||||
return metric;
|
||||
});
|
||||
metrics = metrics;
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@
|
||||
<svelte:fragment slot="actions">
|
||||
<Button
|
||||
external
|
||||
href="#/"
|
||||
href="https://appwrite.io/docs/products/sites/domains#add-a-custom-domain"
|
||||
text
|
||||
event="empty_documentation"
|
||||
size="s"
|
||||
|
||||
+2
-1
@@ -54,7 +54,8 @@
|
||||
<Modal title="Instant rollback" bind:show onSubmit={handleSubmit}>
|
||||
<svelte:fragment slot="description">
|
||||
Rollback is only available for deployments that are <b>ready and previously active</b>. <Link
|
||||
href="#/">Learn more</Link
|
||||
href="https://appwrite.io/docs/products/sites/deployments#instant-rollback"
|
||||
external>Learn more</Link
|
||||
>.
|
||||
</svelte:fragment>
|
||||
<Layout.Stack gap="xl">
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<svelte:fragment slot="actions">
|
||||
<Button
|
||||
external
|
||||
href="#"
|
||||
href="https://appwrite.io/docs/products/sites/logs"
|
||||
secondary
|
||||
event="empty_documentation"
|
||||
size="s"
|
||||
|
||||
@@ -121,14 +121,15 @@
|
||||
</svelte:head>
|
||||
|
||||
<Modal
|
||||
title={state === 'authenticated' ? 'Request access' : 'Sign up or log in to view this preview'}
|
||||
title={state === 'authenticated' ? 'Access required' : 'Sign up or log in to view this preview'}
|
||||
dismissible={false}
|
||||
show
|
||||
hideFooter={state !== 'authenticated'}
|
||||
hideFooter
|
||||
{error}>
|
||||
<span slot="description">
|
||||
{#if state === 'authenticated'}
|
||||
Request access to view this preview. You'll gain access once your request is approved.
|
||||
Access is required to view this preview. You'll be able to see it once an admin invites
|
||||
you to the organization.
|
||||
{/if}
|
||||
</span>
|
||||
<Form onSubmit={handleSubmit}>
|
||||
@@ -225,21 +226,23 @@
|
||||
{data.account.email}
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
<Link
|
||||
variant="muted"
|
||||
on:click={() => {
|
||||
logout(false);
|
||||
state = 'login';
|
||||
}}>Switch account</Link>
|
||||
<div>
|
||||
<Link
|
||||
variant="muted"
|
||||
on:click={() => {
|
||||
logout(false);
|
||||
state = 'login';
|
||||
}}>Switch account</Link>
|
||||
</div>
|
||||
</Layout.Stack>
|
||||
</Card>
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Form>
|
||||
|
||||
<svelte:fragment slot="footer">
|
||||
<!-- <svelte:fragment slot="footer">
|
||||
<Button on:click={requestAccess}>Request access</Button>
|
||||
</svelte:fragment>
|
||||
</svelte:fragment> -->
|
||||
</Modal>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
Reference in New Issue
Block a user