mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge pull request #2682 from appwrite/update-credits
This commit is contained in:
@@ -92,8 +92,8 @@
|
||||
|
||||
<Modal bind:show={showSelectProject} title="Manage projects" onSubmit={updateSelected}>
|
||||
<svelte:fragment slot="description">
|
||||
Choose which {$currentPlan?.projects || 2} projects to keep. Projects over the limit will be
|
||||
blocked after this date.
|
||||
Choose which {$currentPlan?.projects || 2} projects to keep. Projects over the limit will be blocked
|
||||
after this date.
|
||||
</svelte:fragment>
|
||||
|
||||
{#if loading}
|
||||
|
||||
@@ -143,8 +143,8 @@
|
||||
{:else}
|
||||
<Card padding="xs" radius="s">
|
||||
<Typography.Text>
|
||||
Body data is not captured by {resolvedProfile.platform} for your user's security
|
||||
and privacy. To display body data in the Logs tab, use <InlineCode
|
||||
Body data is not captured by {resolvedProfile.platform} 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} variant="muted">Learn more</Link>.
|
||||
</Typography.Text>
|
||||
|
||||
@@ -129,8 +129,8 @@
|
||||
{#if report && !isVersionAtLeast(version, '1.4.0') && $provider.provider === 'appwrite'}
|
||||
<Alert.Inline status="warning">
|
||||
<svelte:fragment slot="title">Functions not available for import</svelte:fragment>
|
||||
To migrate your functions, update the version of the {resolvedProfile.platform} instance
|
||||
you're importing from to a version newer than 1.4
|
||||
To migrate your functions, update the version of the {resolvedProfile.platform} instance you're
|
||||
importing from to a version newer than 1.4
|
||||
</Alert.Inline>
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -81,8 +81,8 @@
|
||||
<svelte:fragment slot="title">Billing alerts</svelte:fragment>
|
||||
{#if !currentPlan.budgeting}
|
||||
Get notified by email when your organization meets a percentage of your budget cap. <b
|
||||
>{tierToPlan(organization.billingPlan).name} organizations will receive one notification
|
||||
at 75% resource usage.</b>
|
||||
>{tierToPlan(organization.billingPlan).name} organizations will receive one notification at
|
||||
75% resource usage.</b>
|
||||
{:else}
|
||||
Get notified by email when your organization meets or exceeds a percentage of your specified
|
||||
billing alert(s).
|
||||
|
||||
@@ -50,8 +50,8 @@
|
||||
<Form onSubmit={updateBudget}>
|
||||
<CardGrid>
|
||||
<svelte:fragment slot="title">Budget cap</svelte:fragment>
|
||||
Restrict your resource usage by setting a budget cap. Cap usage is reset at the beginning of
|
||||
each billing cycle.
|
||||
Restrict your resource usage by setting a budget cap. Cap usage is reset at the beginning of each
|
||||
billing cycle.
|
||||
<svelte:fragment slot="aside">
|
||||
{#if !currentPlan.budgeting}
|
||||
<Alert.Inline status="info" title="Budget caps are a Pro plan feature">
|
||||
|
||||
@@ -81,8 +81,8 @@
|
||||
|
||||
<CardGrid>
|
||||
<svelte:fragment slot="title">Delete organization</svelte:fragment>
|
||||
The organization will be permanently deleted, including all projects and data associated
|
||||
with this organization. This action is irreversible.
|
||||
The organization will be permanently deleted, including all projects and data associated with
|
||||
this organization. This action is irreversible.
|
||||
<svelte:fragment slot="aside">
|
||||
<BoxAvatar>
|
||||
<svelte:fragment slot="image">
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
<CardGrid>
|
||||
<svelte:fragment slot="title">DPA</svelte:fragment>
|
||||
After downloading, have the DPA signed by your organization's compliance authority, such as your
|
||||
CEO or Compliance Manager, and submit it to
|
||||
After downloading, have the DPA signed by your organization's compliance authority, such as your CEO
|
||||
or Compliance Manager, and submit it to
|
||||
<a class="link" href="mailto:privacy@appwrite.io">privacy@appwrite.io</a>.
|
||||
<svelte:fragment slot="aside">
|
||||
<Box>
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
|
||||
<Modal {error} onSubmit={update} bind:show on:close title={`${provider.name} OAuth2 settings`}>
|
||||
<p slot="description">
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more
|
||||
info you can
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more info
|
||||
you can
|
||||
<Link.Anchor
|
||||
class="link"
|
||||
href={oAuthProvider?.docs}
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
|
||||
<Modal {error} bind:show onSubmit={update} on:close title={`${provider.name} OAuth2 settings`}>
|
||||
<svelte:fragment slot="description">
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more
|
||||
info you can
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more info
|
||||
you can
|
||||
<Link.Anchor href={oAuthProvider?.docs} target="_blank" rel="noopener noreferrer"
|
||||
>visit the docs.</Link.Anchor>
|
||||
</svelte:fragment>
|
||||
|
||||
+2
-2
@@ -46,8 +46,8 @@
|
||||
|
||||
<Modal {error} bind:show onSubmit={update} on:close title={`${provider.name} OAuth2 settings`}>
|
||||
<p slot="description">
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more
|
||||
info you can
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more info
|
||||
you can
|
||||
<Link.Anchor
|
||||
class="link"
|
||||
href={oAuthProvider?.docs}
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
|
||||
<Modal {error} bind:show onSubmit={update} on:close title={`${provider.name} OAuth2 settings`}>
|
||||
<p slot="description">
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more
|
||||
info you can
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more info
|
||||
you can
|
||||
<Link.Anchor href={oAuthProvider?.docs} target="_blank" rel="noopener noreferrer"
|
||||
>visit the docs.</Link.Anchor>
|
||||
</p>
|
||||
|
||||
@@ -43,8 +43,8 @@
|
||||
<svelte:fragment slot="title">{provider.name} OAuth2 settings</svelte:fragment>
|
||||
|
||||
<p slot="description">
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more
|
||||
info you can
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more info
|
||||
you can
|
||||
<a class="link" href={oAuthProvider?.docs} target="_blank" rel="noopener noreferrer"
|
||||
>visit the docs.</a>
|
||||
</p>
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
|
||||
<Modal {error} bind:show onSubmit={update} on:close title={`${provider.name} OAuth2 settings`}>
|
||||
<p slot="description">
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more
|
||||
info you can
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more info
|
||||
you can
|
||||
<Link.Anchor
|
||||
class="link"
|
||||
href={oAuthProvider?.docs}
|
||||
|
||||
+2
-2
@@ -45,8 +45,8 @@
|
||||
|
||||
<Modal {error} onSubmit={update} bind:show on:close title={`${provider.name} OAuth2 settings`}>
|
||||
<p slot="description">
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more
|
||||
info you can
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more info
|
||||
you can
|
||||
<a class="link" href={oAuthProvider?.docs} target="_blank" rel="noopener noreferrer">
|
||||
visit the docs.
|
||||
</a>
|
||||
|
||||
@@ -67,8 +67,8 @@
|
||||
|
||||
<Modal {error} onSubmit={update} title="{provider.name} OAuth2 settings" bind:show on:close>
|
||||
<p slot="description">
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more
|
||||
info you can
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more info
|
||||
you can
|
||||
<a class="link" href={oAuthProvider?.docs} target="_blank" rel="noopener noreferrer"
|
||||
>visit the docs.</a>
|
||||
</p>
|
||||
|
||||
@@ -55,8 +55,8 @@
|
||||
on:close
|
||||
title={`${provider.name} OAuth2 settings`}>
|
||||
<p slot="description">
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more
|
||||
info you can
|
||||
To use {provider.name} authentication in your application, first fill in this form. For more info
|
||||
you can
|
||||
<a class="link" href={oAuthProvider?.docs} target="_blank" rel="noopener noreferrer"
|
||||
>visit the docs.</a>
|
||||
</p>
|
||||
|
||||
+2
-2
@@ -43,8 +43,8 @@
|
||||
More info
|
||||
</Tag>
|
||||
<p slot="tooltip">
|
||||
User identities are the user's connected OAuth accounts. <br /> The user can
|
||||
sign in using these identities.
|
||||
User identities are the user's connected OAuth accounts. <br /> The user can sign
|
||||
in using these identities.
|
||||
</p>
|
||||
</Popover>
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -25,8 +25,8 @@
|
||||
</Tag>
|
||||
<p slot="tooltip">
|
||||
User targets include emails, phone numbers, and devices with your app
|
||||
installed.<br /> These targets can subscribe to a topic and receive messages
|
||||
published to it.
|
||||
installed.<br /> These targets can subscribe to a topic and receive messages published
|
||||
to it.
|
||||
</p>
|
||||
</Popover>
|
||||
</div>
|
||||
|
||||
@@ -326,8 +326,8 @@ APPWRITE_ENDPOINT = "${sdk.forProject(page.params.region, page.params.project).c
|
||||
<Icon icon={IconInfo} size="s" />
|
||||
<span slot="tooltip">
|
||||
The hostname that your website will use to interact with the
|
||||
{resolvedProfile.platform} APIs in production or development
|
||||
environments. No protocol or port number required.
|
||||
{resolvedProfile.platform} APIs in production or development environments.
|
||||
No protocol or port number required.
|
||||
</span>
|
||||
</Tooltip>
|
||||
</InputText>
|
||||
|
||||
@@ -171,8 +171,8 @@
|
||||
</Layout.Stack>
|
||||
{:else if isSelfHosted && !isVcsEnabled}
|
||||
<Alert.Inline status="info" title="Installing Git on a self-hosted instance">
|
||||
Before installing Git in a locally hosted {resolvedProfile.platform} project, ensure
|
||||
your environment variables are configured.
|
||||
Before installing Git in a locally hosted {resolvedProfile.platform} project, ensure your
|
||||
environment variables are configured.
|
||||
<svelte:fragment slot="actions">
|
||||
<FormButton
|
||||
compact
|
||||
|
||||
+71
-51
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { Container } from '$lib/layout';
|
||||
import { CardGrid, Card, ProgressBarBig } from '$lib/components';
|
||||
import { showUsageRatesModal, tierToPlan, upgradeURL } from '$lib/stores/billing';
|
||||
import { plansInfo, showUsageRatesModal, upgradeURL } from '$lib/stores/billing';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { bytesToSize, humanFileSize, mbSecondsToGBHours } from '$lib/helpers/sizeConvertion';
|
||||
@@ -9,34 +9,40 @@
|
||||
import { formatNum } from '$lib/helpers/string';
|
||||
import { total } from '$lib/layout/usage.svelte';
|
||||
import { BillingPlan } from '$lib/constants.js';
|
||||
import { base } from '$app/paths';
|
||||
import { resolve } from '$app/paths';
|
||||
import { formatCurrency, formatNumberWithCommas, clampMin } from '$lib/helpers/numbers';
|
||||
import { getCountryName } from '$lib/helpers/diallingCodes.js';
|
||||
import { Accordion, Icon, Layout, Link, Table, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { IconChartSquareBar } from '@appwrite.io/pink-icons-svelte';
|
||||
import { page } from '$app/state';
|
||||
import { isFreePlan, isPaidPlan } from '$lib/helpers/billing.js';
|
||||
import { resolvedProfile } from '$lib/profiles/index.svelte';
|
||||
import { Platform } from '@appwrite.io/console';
|
||||
import { ProfileMode, resolvedProfile } from '$lib/profiles/index.svelte';
|
||||
import type { PageProps } from './$types';
|
||||
|
||||
export let data;
|
||||
const { data, params }: PageProps = $props();
|
||||
|
||||
$: baseRoute = `${base}/project-${page.params.region}-${page.params.project}`;
|
||||
$: network = data.usage.network;
|
||||
$: users = data.usage.users;
|
||||
$: usersTotal = data.usage.usersTotal;
|
||||
$: executions = data.usage.executions;
|
||||
$: executionsTotal = data.usage.executionsTotal;
|
||||
$: storage =
|
||||
const baseRoute = $derived(
|
||||
resolve('/(console)/project-[region]-[project]', {
|
||||
region: params.region,
|
||||
project: params.project
|
||||
})
|
||||
);
|
||||
|
||||
const network = $derived(data.usage.network);
|
||||
const users = $derived(data.usage.users);
|
||||
const usersTotal = $derived(data.usage.usersTotal);
|
||||
const executions = $derived(data.usage.executions);
|
||||
const executionsTotal = $derived(data.usage.executionsTotal);
|
||||
const storage = $derived(
|
||||
data.usage.filesStorageTotal +
|
||||
data.usage.deploymentsStorageTotal +
|
||||
data.usage.buildsStorageTotal;
|
||||
$: imageTransformations = data.usage.imageTransformations;
|
||||
$: imageTransformationsTotal = data.usage.imageTransformationsTotal;
|
||||
$: dbReads = data.usage.databasesReads;
|
||||
$: dbWrites = data.usage.databasesWrites;
|
||||
data.usage.deploymentsStorageTotal +
|
||||
data.usage.buildsStorageTotal
|
||||
);
|
||||
const imageTransformations = $derived(data.usage.imageTransformations);
|
||||
const imageTransformationsTotal = $derived(data.usage.imageTransformationsTotal);
|
||||
const dbReads = $derived(data.usage.databasesReads);
|
||||
const dbWrites = $derived(data.usage.databasesWrites);
|
||||
|
||||
$: legendData = [
|
||||
const legendData = $derived([
|
||||
{
|
||||
name: 'Reads',
|
||||
value: clampMin(data.usage.databasesReads.reduce((sum, item) => sum + item.value, 0))
|
||||
@@ -45,10 +51,10 @@
|
||||
name: 'Writes',
|
||||
value: clampMin(data.usage.databasesWrites.reduce((sum, item) => sum + item.value, 0))
|
||||
}
|
||||
];
|
||||
]);
|
||||
|
||||
const tier = data?.currentInvoice?.plan ?? $organization?.billingPlan;
|
||||
const plan = tierToPlan(tier).name;
|
||||
const plan = $derived($plansInfo.get(data?.currentInvoice?.plan ?? $organization?.billingPlan));
|
||||
const planName = $derived(plan.name);
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
@@ -66,19 +72,19 @@
|
||||
<p class="text">
|
||||
On the Scale plan, you'll be charged only for any usage that exceeds the thresholds
|
||||
per resource listed below. <Link.Button
|
||||
on:click={() => ($showUsageRatesModal = true)}
|
||||
onclick={() => ($showUsageRatesModal = true)}
|
||||
>Learn more about plan usage limits.</Link.Button>
|
||||
</p>
|
||||
{:else if isPaidPlan($organization.billingPlan)}
|
||||
<p class="text">
|
||||
On the Pro plan, you'll be charged only for any usage that exceeds the thresholds
|
||||
per resource listed below. <Link.Button
|
||||
on:click={() => ($showUsageRatesModal = true)}
|
||||
onclick={() => ($showUsageRatesModal = true)}
|
||||
>Learn more about plan usage limits.</Link.Button>
|
||||
</p>
|
||||
{:else if isFreePlan($organization?.billingPlan)}
|
||||
<p class="text">
|
||||
If you exceed the limits of the {plan} plan, services for your projects may be disrupted.
|
||||
If you exceed the limits of the {planName} plan, services for your projects may be disrupted.
|
||||
<Link.Anchor href={$upgradeURL} class="link"
|
||||
>Upgrade for greater capacity</Link.Anchor
|
||||
>.
|
||||
@@ -86,40 +92,54 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if resolvedProfile.platform === Platform.Imagine}
|
||||
{#if resolvedProfile.id === ProfileMode.STUDIO}
|
||||
<CardGrid>
|
||||
<svelte:fragment slot="title">Imagine Credits</svelte:fragment>
|
||||
Total Imagine credits consumed across your project. Resets at the start of each billing cycle.
|
||||
<svelte:fragment slot="title">Credits</svelte:fragment>
|
||||
Current credit usage included in your plan.
|
||||
<svelte:fragment slot="aside">
|
||||
{#if data.usage.imagineCredits}
|
||||
{@const creditsTotal = data.usage.imagineCredits.reduce(
|
||||
(sum, item) => sum + item.value,
|
||||
0
|
||||
)}
|
||||
<Layout.Stack gap="s" direction="row" alignItems="baseline">
|
||||
<Typography.Title>
|
||||
{formatNumberWithCommas(creditsTotal)}
|
||||
</Typography.Title>
|
||||
<Typography.Text>Credits</Typography.Text>
|
||||
{@const creditsLimit = plan.limits?.credits ?? plan.limits?.dailyCredits ?? 0}
|
||||
{@const percentageUsed =
|
||||
creditsLimit > 0 ? Math.round((creditsTotal / creditsLimit) * 100) : 0}
|
||||
|
||||
<Layout.Stack direction="row" justifyContent="space-between">
|
||||
<Layout.Stack gap="s" direction="row" alignItems="baseline" inline>
|
||||
<Typography.Title>
|
||||
{formatNumberWithCommas(creditsTotal)}
|
||||
</Typography.Title>
|
||||
<Typography.Text>Credits used</Typography.Text>
|
||||
</Layout.Stack>
|
||||
|
||||
<Layout.Stack direction="row" gap="xs" alignItems="center" inline>
|
||||
<Typography.Text>
|
||||
{percentageUsed}%
|
||||
</Typography.Text>
|
||||
</Layout.Stack>
|
||||
</Layout.Stack>
|
||||
{#if data.usage.imagineCredits.length > 0}
|
||||
<BarChart
|
||||
options={{
|
||||
yAxis: {
|
||||
axisLabel: {
|
||||
formatter: formatNum
|
||||
}
|
||||
|
||||
<ProgressBarBig
|
||||
progressValue={creditsTotal}
|
||||
progressMax={creditsLimit}
|
||||
progressBarData={[
|
||||
{
|
||||
size: creditsTotal,
|
||||
color: 'var(--bgcolor-neutral-invert)',
|
||||
tooltip: {
|
||||
title: 'Credits',
|
||||
label: formatNumberWithCommas(creditsTotal)
|
||||
}
|
||||
}}
|
||||
series={[
|
||||
{
|
||||
name: 'Credits',
|
||||
data: [
|
||||
...data.usage.imagineCredits.map((e) => [e.date, e.value])
|
||||
]
|
||||
}
|
||||
]} />
|
||||
{/if}
|
||||
}
|
||||
]} />
|
||||
|
||||
<Layout.Stack direction="row" justifyContent="space-between">
|
||||
<Typography.Text>{formatNumberWithCommas(creditsTotal)}</Typography.Text>
|
||||
|
||||
<Typography.Text>{formatNumberWithCommas(creditsLimit)}</Typography.Text>
|
||||
</Layout.Stack>
|
||||
{:else}
|
||||
<Card isDashed>
|
||||
<Layout.Stack gap="xs" alignItems="center" justifyContent="center">
|
||||
|
||||
+2
-2
@@ -184,8 +184,8 @@
|
||||
<Form onSubmit={update}>
|
||||
<CardGrid>
|
||||
<svelte:fragment slot="title">Build settings</svelte:fragment>
|
||||
Default build settings are configured based on your framework, ensuring optimal performance.
|
||||
Adjust the settings here if needed.
|
||||
Default build settings are configured based on your framework, ensuring optimal performance. Adjust
|
||||
the settings here if needed.
|
||||
<svelte:fragment slot="aside">
|
||||
{@const adapterData = adapterDataList.find(
|
||||
(adapterData) => adapterData.framework === frameworkKey.toLowerCase()
|
||||
|
||||
+2
-2
@@ -64,8 +64,8 @@
|
||||
<Form onSubmit={updateRuntime}>
|
||||
<CardGrid>
|
||||
<svelte:fragment slot="title">Runtime settings</svelte:fragment>
|
||||
Select the runtime for building and serving your site. Version changes apply on redeploy and
|
||||
can be updated here.
|
||||
Select the runtime for building and serving your site. Version changes apply on redeploy and can
|
||||
be updated here.
|
||||
<svelte:fragment slot="aside">
|
||||
<InputSelect
|
||||
label="Build runtime"
|
||||
|
||||
Reference in New Issue
Block a user