mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Merge branch 'appwrite:main' into fix-977-email-failed-modal-message-improve
This commit is contained in:
@@ -9,12 +9,14 @@
|
||||
import { organization } from '$lib/stores/organization';
|
||||
</script>
|
||||
|
||||
{#if $organization?.$id && $organization?.billingPlan === BillingPlan.STARTER && $readOnly && !hideBillingHeaderRoutes.includes($page.url.pathname)}
|
||||
{#if $organization?.$id && $organization?.billingPlan === BillingPlan.FREE && $readOnly && !hideBillingHeaderRoutes.includes($page.url.pathname)}
|
||||
<HeaderAlert
|
||||
type="error"
|
||||
title={`${$organization.name} usage has reached the ${tierToPlan($organization.billingPlan).name} plan limit`}>
|
||||
<svelte:fragment>
|
||||
Usage for the <b>{$organization.name}</b> organization has reached the limits of the Starter
|
||||
Usage for the <b>{$organization.name}</b> organization has reached the limits of the {tierToPlan(
|
||||
$organization.billingPlan
|
||||
).name}
|
||||
plan. Consider upgrading to increase your resource usage.
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="buttons">
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<SecondaryTabsItem
|
||||
disabled={selectedTab === 'tier-0'}
|
||||
on:click={() => (selectedTab = 'tier-0')}>
|
||||
Starter
|
||||
Free
|
||||
</SecondaryTabsItem>
|
||||
<SecondaryTabsItem
|
||||
disabled={selectedTab === 'tier-1'}
|
||||
@@ -38,7 +38,7 @@
|
||||
{:else if selectedTab === 'tier-1'}
|
||||
<h3 class="u-bold body-text-1">{plan.name} plan</h3>
|
||||
<ul class="un-order-list u-margin-block-start-8">
|
||||
<li>Everything in the Starter plan, plus:</li>
|
||||
<li>Everything in the Free plan, plus:</li>
|
||||
<li>Unlimited databases, buckets, functions</li>
|
||||
<li>{plan.bandwidth}GB bandwidth</li>
|
||||
<li>{plan.storage}GB storage</li>
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
import { onMount } from 'svelte';
|
||||
import type { OrganizationUsage } from '$lib/sdk/billing';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { BillingPlan } from '$lib/constants';
|
||||
|
||||
export let tier: Tier;
|
||||
|
||||
@@ -51,15 +52,16 @@
|
||||
$organization.billingNextInvoiceDate
|
||||
)}
|
||||
</svelte:fragment>
|
||||
Following payment of your final invoice, your organization will switch to the Starter plan. {#if excess?.members > 0}All
|
||||
team members except the owner will be removed on that date.{/if} Service disruptions may
|
||||
occur unless resource usage is reduced.
|
||||
Following payment of your final invoice, your organization will switch to the {tierToPlan(
|
||||
BillingPlan.FREE
|
||||
).name} plan. {#if excess?.members > 0}All team members except the owner will be removed on
|
||||
that date.{/if} Service disruptions may occur unless resource usage is reduced.
|
||||
<!-- Any executions, bandwidth, or messaging usage will be reset at that time. -->
|
||||
<svelte:fragment slot="buttons">
|
||||
<Button
|
||||
text
|
||||
external
|
||||
href="https://appwrite.io/docs/advanced/platform/starter#reaching-resource-limits">
|
||||
href="https://appwrite.io/docs/advanced/platform/free#reaching-resource-limits">
|
||||
Learn more
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
|
||||
@@ -49,14 +49,13 @@
|
||||
}
|
||||
];
|
||||
|
||||
$: isFree = org.billingPlan === BillingPlan.STARTER;
|
||||
$: isFree = org.billingPlan === BillingPlan.FREE;
|
||||
</script>
|
||||
|
||||
<Modal bind:show size="big" headerDivider={false} title="Usage rates">
|
||||
{#if isFree}
|
||||
Usage on the Starter plan is limited for the following resources. Next billing period: {toLocaleDate(
|
||||
nextDate
|
||||
)}.
|
||||
Usage on the {$plansInfo?.get(BillingPlan.FREE).name} plan is limited for the following resources.
|
||||
Next billing period: {toLocaleDate(nextDate)}.
|
||||
{:else if org.billingPlan === BillingPlan.PRO}
|
||||
<p>
|
||||
Usage on the Pro plan will be charged at the end of each billing period at the following
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
<Button
|
||||
fullWidth
|
||||
href={$upgradeURL}
|
||||
@@ -63,6 +63,7 @@
|
||||
<div class="u-margin-block-start-8 u-width-full-line">
|
||||
{#key $app.themeInUse}
|
||||
<iframe
|
||||
style="color-scheme: none"
|
||||
title="Appwrite Status"
|
||||
src={`https://status.appwrite.online/badge?theme=${
|
||||
$app.themeInUse === 'dark' ? 'dark' : 'light'
|
||||
|
||||
@@ -367,7 +367,7 @@ export const eventServices: Array<EventService> = [
|
||||
];
|
||||
|
||||
export enum BillingPlan {
|
||||
STARTER = 'tier-0',
|
||||
FREE = 'tier-0',
|
||||
PRO = 'tier-1',
|
||||
SCALE = 'tier-2'
|
||||
}
|
||||
@@ -387,7 +387,7 @@ export const feedbackDowngradeOptions = [
|
||||
},
|
||||
{
|
||||
value: 'starter',
|
||||
label: 'The Starter plan is enough for my projects'
|
||||
label: 'The Free plan is enough for my projects'
|
||||
},
|
||||
{
|
||||
value: 'budget',
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
Logs are retained in rolling {hoursToDays(limit)} intervals with the
|
||||
{tierToPlan($organization.billingPlan).name}
|
||||
plan.
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
<Button link on:click={upgradeMethod}>Upgrade</Button> to increase your log
|
||||
retention for a longer period.
|
||||
{/if}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
export let title: string;
|
||||
export let tooltipContent =
|
||||
$organization.billingPlan === BillingPlan.STARTER
|
||||
$organization.billingPlan === BillingPlan.FREE
|
||||
? `Upgrade to add more ${title.toLocaleLowerCase()}`
|
||||
: `You've reached the ${title.toLocaleLowerCase()} limit for the ${
|
||||
tierToPlan($organization.billingPlan).name
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
|
||||
$: tier = tierToPlan($organization?.billingPlan)?.name;
|
||||
$: hasProjectLimitation =
|
||||
checkForProjectLimitation(serviceId) && $organization?.billingPlan === BillingPlan.STARTER;
|
||||
checkForProjectLimitation(serviceId) && $organization?.billingPlan === BillingPlan.FREE;
|
||||
$: hasUsageFees = hasProjectLimitation
|
||||
? checkForUsageFees($organization?.billingPlan, serviceId)
|
||||
: false;
|
||||
@@ -88,7 +88,7 @@
|
||||
})
|
||||
.join(', ')}
|
||||
<slot name="alert" {limit} {tier} {title} {upgradeMethod} {hasUsageFees} {services}>
|
||||
{#if $organization?.billingPlan !== BillingPlan.STARTER && hasUsageFees}
|
||||
{#if $organization?.billingPlan !== BillingPlan.FREE && hasUsageFees}
|
||||
<Alert type="info" isStandalone>
|
||||
<span class="text">
|
||||
You've reached the {services} limit for the {tier} plan.
|
||||
@@ -135,7 +135,7 @@
|
||||
<p class="text">
|
||||
You are limited to {limit}
|
||||
{title.toLocaleLowerCase()} per project on the {tier} plan.
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}<Button
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}<Button
|
||||
link
|
||||
href={$upgradeURL}
|
||||
on:click={() =>
|
||||
@@ -158,7 +158,7 @@
|
||||
<p class="text">
|
||||
You are limited to {limit}
|
||||
{title.toLocaleLowerCase()} per organization on the {tier} plan.
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
<Button link href={$upgradeURL}>Upgrade</Button>
|
||||
for additional {title.toLocaleLowerCase()}.
|
||||
{/if}
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
|
||||
<div class="main-header-end">
|
||||
<nav class="u-flex is-only-desktop u-cross-center">
|
||||
{#if isCloud && $organization?.billingPlan === BillingPlan.STARTER && !$page.url.pathname.startsWith('/console/account')}
|
||||
{#if isCloud && $organization?.billingPlan === BillingPlan.FREE && !$page.url.pathname.startsWith('/console/account')}
|
||||
<Button
|
||||
disabled={$organization?.markedForDeletion}
|
||||
href={$upgradeURL}
|
||||
|
||||
@@ -310,7 +310,7 @@
|
||||
<Alert>
|
||||
Logs are retained in rolling {hoursToDays(limit)} intervals
|
||||
with the {tier} plan.
|
||||
{#if $organization.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization.billingPlan === BillingPlan.FREE}
|
||||
<Button link href={$upgradeURL}>Upgrade</Button> to increase
|
||||
your log retention for a longer period.
|
||||
{/if}
|
||||
|
||||
@@ -40,7 +40,7 @@ export const readOnly = writable<boolean>(false);
|
||||
|
||||
export function tierToPlan(tier: Tier) {
|
||||
switch (tier) {
|
||||
case BillingPlan.STARTER:
|
||||
case BillingPlan.FREE:
|
||||
return tierFree;
|
||||
case BillingPlan.PRO:
|
||||
return tierPro;
|
||||
@@ -115,7 +115,7 @@ export type TierData = {
|
||||
};
|
||||
|
||||
export const tierFree: TierData = {
|
||||
name: 'Starter',
|
||||
name: 'Free',
|
||||
description: 'For personal hobby projects of small scale and students.'
|
||||
};
|
||||
|
||||
@@ -171,7 +171,7 @@ export function isServiceLimited(serviceId: PlanServices, plan: Tier, total: num
|
||||
}
|
||||
|
||||
export function calculateTrialDay(org: Organization) {
|
||||
if (org?.billingPlan === BillingPlan.STARTER) return false;
|
||||
if (org?.billingPlan === BillingPlan.FREE) return false;
|
||||
const endDate = new Date(org?.billingStartDate);
|
||||
const today = new Date();
|
||||
|
||||
@@ -185,7 +185,7 @@ export function calculateTrialDay(org: Organization) {
|
||||
}
|
||||
|
||||
export async function checkForUsageLimit(org: Organization) {
|
||||
if (org?.billingPlan !== BillingPlan.STARTER) {
|
||||
if (org?.billingPlan !== BillingPlan.FREE) {
|
||||
readOnly.set(false);
|
||||
return;
|
||||
}
|
||||
@@ -221,9 +221,9 @@ export async function checkForUsageLimit(org: Organization) {
|
||||
if (now - lastNotification < 1000 * 60 * 60 * 24) return;
|
||||
|
||||
localStorage.setItem('limitReachedNotification', now.toString());
|
||||
let message = `<b>${org.name}</b> has reached <b>75%</b> of the Starter plan's ${resources.find((r) => r.value >= 75).name} limit. Upgrade to ensure there are no service disruptions.`;
|
||||
let message = `<b>${org.name}</b> has reached <b>75%</b> of the ${tierToPlan(BillingPlan.FREE).name} plan's ${resources.find((r) => r.value >= 75).name} limit. Upgrade to ensure there are no service disruptions.`;
|
||||
if (resources.filter((r) => r.value >= 75)?.length > 1) {
|
||||
message = `Usage for <b>${org.name}</b> has reached 75% of the Starter plan limit. Upgrade to ensure there are no service disruptions.`;
|
||||
message = `Usage for <b>${org.name}</b> has reached 75% of the ${tierToPlan(BillingPlan.FREE).name} plan limit. Upgrade to ensure there are no service disruptions.`;
|
||||
}
|
||||
addNotification({
|
||||
type: 'warning',
|
||||
@@ -255,7 +255,7 @@ export async function checkForUsageLimit(org: Organization) {
|
||||
}
|
||||
|
||||
export async function checkPaymentAuthorizationRequired(org: Organization) {
|
||||
if (org.billingPlan === BillingPlan.STARTER) return;
|
||||
if (org.billingPlan === BillingPlan.FREE) return;
|
||||
|
||||
const invoices = await sdk.forConsole.billing.listInvoices(org.$id, [
|
||||
Query.equal('status', 'requires_authentication')
|
||||
@@ -351,7 +351,7 @@ export async function checkForMandate(org: Organization) {
|
||||
|
||||
export async function checkForMissingPaymentMethod() {
|
||||
const orgs = await sdk.forConsole.billing.listOrganization([
|
||||
Query.notEqual('billingPlan', BillingPlan.STARTER),
|
||||
Query.notEqual('billingPlan', BillingPlan.FREE),
|
||||
Query.isNull('paymentMethodId'),
|
||||
Query.isNull('backupPaymentMethodId')
|
||||
]);
|
||||
|
||||
@@ -149,6 +149,7 @@
|
||||
await goto(`/console/project-${$project.$id}/auth/security#${heading}`);
|
||||
scrollBy({ top: -100 });
|
||||
},
|
||||
disabled: !$project?.$id,
|
||||
group: 'security',
|
||||
icon: 'pencil'
|
||||
}) as const
|
||||
@@ -161,7 +162,8 @@
|
||||
callback: () => {
|
||||
goto(`/console/project-${$project.$id}/settings`);
|
||||
},
|
||||
disabled: isOnSettingsLayout && $page.url.pathname.endsWith('settings'),
|
||||
disabled:
|
||||
!$project?.$id || (isOnSettingsLayout && $page.url.pathname.endsWith('settings')),
|
||||
group: isOnSettingsLayout ? 'navigation' : 'settings',
|
||||
rank: isOnSettingsLayout ? 40 : -1
|
||||
},
|
||||
@@ -172,7 +174,8 @@
|
||||
callback: () => {
|
||||
goto(`/console/project-${$project.$id}/settings/domains`);
|
||||
},
|
||||
disabled: isOnSettingsLayout && $page.url.pathname.includes('domains'),
|
||||
disabled:
|
||||
!$project?.$id || (isOnSettingsLayout && $page.url.pathname.includes('domains')),
|
||||
group: isOnSettingsLayout ? 'navigation' : 'settings',
|
||||
rank: isOnSettingsLayout ? 30 : -1
|
||||
},
|
||||
@@ -182,7 +185,8 @@
|
||||
callback: () => {
|
||||
goto(`/console/project-${$project.$id}/settings/webhooks`);
|
||||
},
|
||||
disabled: isOnSettingsLayout && $page.url.pathname.includes('webhooks'),
|
||||
disabled:
|
||||
!$project?.$id || (isOnSettingsLayout && $page.url.pathname.includes('webhooks')),
|
||||
group: isOnSettingsLayout ? 'navigation' : 'settings',
|
||||
|
||||
rank: isOnSettingsLayout ? 20 : -1
|
||||
@@ -193,7 +197,8 @@
|
||||
callback: () => {
|
||||
goto(`/console/project-${$project.$id}/settings/migrations`);
|
||||
},
|
||||
disabled: isOnSettingsLayout && $page.url.pathname.includes('migrations'),
|
||||
disabled:
|
||||
!$project?.$id || (isOnSettingsLayout && $page.url.pathname.includes('migrations')),
|
||||
group: isOnSettingsLayout ? 'navigation' : 'settings',
|
||||
|
||||
rank: isOnSettingsLayout ? 10 : -1
|
||||
@@ -202,9 +207,10 @@
|
||||
label: 'Go to SMTP settings',
|
||||
keys: isOnSettingsLayout ? ['g', 's'] : undefined,
|
||||
callback: () => {
|
||||
console.log('withing callback of go to smtp');
|
||||
goto(`/console/project-${$project.$id}/settings/smtp`);
|
||||
},
|
||||
disabled: isOnSettingsLayout && $page.url.pathname.includes('smtp'),
|
||||
disabled: !$project?.$id || (isOnSettingsLayout && $page.url.pathname.includes('smtp')),
|
||||
group: isOnSettingsLayout ? 'navigation' : 'settings',
|
||||
rank: -1
|
||||
},
|
||||
@@ -260,7 +266,7 @@
|
||||
if (isCloud) {
|
||||
await checkForUsageLimit(org);
|
||||
checkForMarkedForDeletion(org);
|
||||
if (org?.billingPlan !== BillingPlan.STARTER) {
|
||||
if (org?.billingPlan !== BillingPlan.FREE) {
|
||||
await paymentExpired(org);
|
||||
await checkPaymentAuthorizationRequired(org);
|
||||
await checkForMandate(org);
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="status">
|
||||
{#if isCloudOrg(organization)}
|
||||
{#if organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if organization?.billingPlan === BillingPlan.FREE}
|
||||
<div
|
||||
class="u-flex u-cross-center"
|
||||
use:tooltip={{
|
||||
@@ -81,7 +81,7 @@
|
||||
<Pill>FREE</Pill>
|
||||
</div>
|
||||
{/if}
|
||||
{#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.STARTER && $plansInfo.get(organization.billingPlan)?.trialDays}
|
||||
{#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.FREE && $plansInfo.get(organization.billingPlan)?.trialDays}
|
||||
<div
|
||||
class="u-flex u-cross-center"
|
||||
use:tooltip={{
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
$: anyOrgFree = $organizationList.teams?.find(
|
||||
(org) => (org as Organization)?.billingPlan === BillingPlan.STARTER
|
||||
(org) => (org as Organization)?.billingPlan === BillingPlan.FREE
|
||||
);
|
||||
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$/i;
|
||||
let previousPage: string = `${base}/console`;
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
let methods: PaymentList;
|
||||
let name: string;
|
||||
let billingPlan: BillingPlan = BillingPlan.STARTER;
|
||||
let billingPlan: BillingPlan = BillingPlan.FREE;
|
||||
let paymentMethodId: string;
|
||||
let collaborators: string[] = [];
|
||||
let couponData: Partial<Coupon> = {
|
||||
@@ -94,11 +94,11 @@
|
||||
try {
|
||||
let org: Organization;
|
||||
|
||||
if (billingPlan === BillingPlan.STARTER) {
|
||||
if (billingPlan === BillingPlan.FREE) {
|
||||
org = await sdk.forConsole.billing.createOrganization(
|
||||
ID.unique(),
|
||||
name,
|
||||
BillingPlan.STARTER,
|
||||
BillingPlan.FREE,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -108,7 +108,7 @@
|
||||
await sdk.forConsole.billing.createOrganization(
|
||||
ID.unique(),
|
||||
'Personal Projects',
|
||||
BillingPlan.STARTER,
|
||||
BillingPlan.FREE,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -175,7 +175,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: freePlan = $plansInfo.get(BillingPlan.STARTER);
|
||||
$: freePlan = $plansInfo.get(BillingPlan.FREE);
|
||||
$: proPlan = $plansInfo.get(BillingPlan.PRO);
|
||||
$: if (billingPlan === BillingPlan.PRO) {
|
||||
loadPaymentMethods();
|
||||
@@ -275,7 +275,7 @@
|
||||
{/if}
|
||||
</Form>
|
||||
<svelte:fragment slot="aside">
|
||||
{#if billingPlan !== BillingPlan.STARTER}
|
||||
{#if billingPlan !== BillingPlan.FREE}
|
||||
<EstimatedTotalBox
|
||||
{billingPlan}
|
||||
{collaborators}
|
||||
|
||||
@@ -49,9 +49,9 @@
|
||||
<Alert type="info">
|
||||
<svelte:fragment slot="title">Get ready for Appwrite Pro</svelte:fragment>
|
||||
We will soon introduce the much-anticipated Pro plan. Your account will continue to have
|
||||
access to <b>one free Starter organization</b>. If you manage more than one
|
||||
organization, you will need to either upgrade to the Pro plan, transfer your projects to
|
||||
a Pro organization, or migrate to self-hosting.
|
||||
access to <b>one free organization</b>. If you manage more than one organization, you
|
||||
will need to either upgrade to the Pro plan, transfer your projects to a Pro
|
||||
organization, or migrate to self-hosting.
|
||||
<svelte:fragment slot="buttons">
|
||||
<Button href="https://appwrite.io/pricing" external text>Learn more</Button>
|
||||
</svelte:fragment>
|
||||
|
||||
@@ -26,12 +26,12 @@
|
||||
const options = isCloud
|
||||
? [
|
||||
{
|
||||
value: BillingPlan.STARTER,
|
||||
label: `Starter - ${formatCurrency($plansInfo.get(BillingPlan.STARTER).price)}/month`
|
||||
value: BillingPlan.FREE,
|
||||
label: `${tierToPlan(BillingPlan.FREE).name} - ${formatCurrency($plansInfo.get(BillingPlan.FREE).price)}/month`
|
||||
},
|
||||
{
|
||||
value: BillingPlan.PRO,
|
||||
label: `Pro - ${formatCurrency($plansInfo.get(BillingPlan.PRO).price)}/month + add-ons`
|
||||
label: `${tierToPlan(BillingPlan.PRO).name} - ${formatCurrency($plansInfo.get(BillingPlan.PRO).price)}/month + add-ons`
|
||||
}
|
||||
]
|
||||
: [];
|
||||
@@ -50,7 +50,7 @@
|
||||
async function handleSubmit() {
|
||||
const orgName = name?.length ? name : 'Personal Projects';
|
||||
if (isCloud) {
|
||||
if (plan === BillingPlan.STARTER) {
|
||||
if (plan === BillingPlan.FREE) {
|
||||
try {
|
||||
const org = await sdk.forConsole.billing.createOrganization(
|
||||
id ?? ID.unique(),
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import PaymentHistory from './paymentHistory.svelte';
|
||||
import TaxId from './taxId.svelte';
|
||||
import { Alert, Heading } from '$lib/components';
|
||||
import { failedInvoice, paymentMethods, upgradeURL } from '$lib/stores/billing';
|
||||
import { failedInvoice, paymentMethods, tierToPlan, upgradeURL } from '$lib/stores/billing';
|
||||
import type { PaymentMethodData } from '$lib/sdk/billing';
|
||||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
@@ -111,8 +111,10 @@
|
||||
{/if}
|
||||
{#if $organization?.billingPlanDowngrade}
|
||||
<Alert type="info" class="common-section">
|
||||
Your organization will change to a Starter plan once your current billing cycle ends and
|
||||
your invoice is paid on {toLocaleDate($organization.billingNextInvoiceDate)}.
|
||||
Your organization will change to a {tierToPlan(BillingPlan.FREE).name} plan once your current
|
||||
billing cycle ends and your invoice is paid on {toLocaleDate(
|
||||
$organization.billingNextInvoiceDate
|
||||
)}.
|
||||
</Alert>
|
||||
{/if}
|
||||
<div class="common-section">
|
||||
@@ -124,7 +126,7 @@
|
||||
<BillingAddress billingAddress={data?.billingAddress} />
|
||||
<TaxId />
|
||||
<BudgetCap />
|
||||
{#if $organization?.billingPlan !== BillingPlan.STARTER && !!$organization?.billingBudget}
|
||||
{#if $organization?.billingPlan !== BillingPlan.FREE && !!$organization?.billingBudget}
|
||||
<BudgetAlert />
|
||||
{/if}
|
||||
<AvailableCredit />
|
||||
|
||||
@@ -67,12 +67,12 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<CardGrid hideFooter={$organization?.billingPlan !== BillingPlan.STARTER}>
|
||||
<CardGrid hideFooter={$organization?.billingPlan !== BillingPlan.FREE}>
|
||||
<Heading tag="h2" size="6">Available credit</Heading>
|
||||
|
||||
<p class="text">Appwrite credit will automatically be applied to your next invoice.</p>
|
||||
<svelte:fragment slot="aside">
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
<Alert type="info">
|
||||
<svelte:fragment slot="title">Upgrade to Pro to add credits</svelte:fragment>
|
||||
Upgrade to a Pro plan to add credits to your organization. For more information on what
|
||||
@@ -129,7 +129,7 @@
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="actions">
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
<Button
|
||||
secondary
|
||||
href={$upgradeURL}
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
class="link">Learn more about usage rates.</button>
|
||||
</p>
|
||||
<svelte:fragment slot="aside">
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
<Alert type="info">
|
||||
<svelte:fragment slot="title">
|
||||
Budget caps are a Pro plan feature
|
||||
@@ -92,7 +92,7 @@
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="actions">
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
<Button
|
||||
secondary
|
||||
href={$upgradeURL}
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
{isTrial ? formatCurrency(0) : formatCurrency(currentPlan?.price)}
|
||||
</div>
|
||||
</CollapsibleItem>
|
||||
{#if $organization?.billingPlan !== BillingPlan.STARTER && extraUsage}
|
||||
{#if $organization?.billingPlan !== BillingPlan.FREE && extraUsage}
|
||||
<CollapsibleItem isInfo gap={8}>
|
||||
<svelte:fragment slot="beforetitle">
|
||||
<span class="body-text-2"><b>Add-ons</b></span><span class="inline-tag"
|
||||
@@ -147,7 +147,7 @@
|
||||
}}></span>
|
||||
</span>
|
||||
<div class="body-text-2 u-margin-inline-start-auto">
|
||||
{$organization?.billingPlan === BillingPlan.STARTER
|
||||
{$organization?.billingPlan === BillingPlan.FREE
|
||||
? formatCurrency(0)
|
||||
: formatCurrency(currentInvoice?.amount ?? 0)}
|
||||
</div>
|
||||
@@ -155,7 +155,7 @@
|
||||
</Collapsible>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="actions">
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
<div class="u-flex u-gap-16 u-flex-wrap">
|
||||
<Button text href={`${base}/console/organization-${$organization?.$id}/usage`}>
|
||||
View estimated usage
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
export let data;
|
||||
|
||||
$: anyOrgFree = $organizationList.teams?.find(
|
||||
(org) => (org as Organization)?.billingPlan === BillingPlan.STARTER
|
||||
(org) => (org as Organization)?.billingPlan === BillingPlan.FREE
|
||||
);
|
||||
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$/i;
|
||||
let previousPage: string = `${base}/console`;
|
||||
@@ -106,7 +106,7 @@
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
if (billingPlan === BillingPlan.STARTER) {
|
||||
if (billingPlan === BillingPlan.FREE) {
|
||||
await downgrade();
|
||||
} else {
|
||||
await upgrade();
|
||||
@@ -237,7 +237,7 @@
|
||||
|
||||
$: isUpgrade = billingPlan > $organization.billingPlan;
|
||||
$: isDowngrade = billingPlan < $organization.billingPlan;
|
||||
$: freePlan = $plansInfo.get(BillingPlan.STARTER);
|
||||
$: freePlan = $plansInfo.get(BillingPlan.FREE);
|
||||
$: proPlan = $plansInfo.get(BillingPlan.PRO);
|
||||
$: if (billingPlan === BillingPlan.PRO) {
|
||||
loadPaymentMethods();
|
||||
@@ -266,8 +266,10 @@
|
||||
</p>
|
||||
{#if anyOrgFree && billingPlan === BillingPlan.PRO}
|
||||
<Alert type="warning" class="u-margin-block-16">
|
||||
You are limited to one Starter organization per account. Consider upgrading or
|
||||
deleting <Button link href={`${base}/console/organization-${anyOrgFree.$id}`}
|
||||
You are limited to one {tierToPlan(BillingPlan.FREE).name} organization per account.
|
||||
Consider upgrading or deleting <Button
|
||||
link
|
||||
href={`${base}/console/organization-${anyOrgFree.$id}`}
|
||||
>{anyOrgFree.name}</Button
|
||||
>.
|
||||
</Alert>
|
||||
@@ -289,7 +291,7 @@
|
||||
class:u-opacity-50={disabled}>
|
||||
<h4 class="body-text-2 u-bold">
|
||||
{tierFree.name}
|
||||
{#if $organization.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization.billingPlan === BillingPlan.FREE}
|
||||
<span class="inline-tag">Current plan</span>
|
||||
{/if}
|
||||
</h4>
|
||||
@@ -324,7 +326,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
{#if isDowngrade}
|
||||
<PlanExcess tier={BillingPlan.STARTER} class="u-margin-block-start-24" />
|
||||
<PlanExcess tier={BillingPlan.FREE} class="u-margin-block-start-24" />
|
||||
{/if}
|
||||
{#if billingPlan === BillingPlan.PRO && $organization.billingPlan !== BillingPlan.PRO}
|
||||
<FormList class="u-margin-block-start-16">
|
||||
@@ -348,7 +350,7 @@
|
||||
</Button>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if !isUpgrade && billingPlan === BillingPlan.STARTER && $organization.billingPlan !== BillingPlan.STARTER}
|
||||
{#if !isUpgrade && billingPlan === BillingPlan.FREE && $organization.billingPlan !== BillingPlan.FREE}
|
||||
<FormList class="u-margin-block-start-16">
|
||||
<InputSelect
|
||||
id="reason"
|
||||
@@ -366,7 +368,7 @@
|
||||
{/if}
|
||||
</Form>
|
||||
<svelte:fragment slot="aside">
|
||||
{#if billingPlan !== BillingPlan.STARTER && $organization.billingPlan !== BillingPlan.PRO}
|
||||
{#if billingPlan !== BillingPlan.FREE && $organization.billingPlan !== BillingPlan.PRO}
|
||||
<EstimatedTotalBox
|
||||
{billingPlan}
|
||||
{collaborators}
|
||||
|
||||
@@ -107,10 +107,10 @@
|
||||
<span class="u-trim">
|
||||
{$organization.name}
|
||||
</span>
|
||||
{#if isCloud && $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if isCloud && $organization?.billingPlan === BillingPlan.FREE}
|
||||
<Pill>FREE</Pill>
|
||||
{/if}
|
||||
{#if isCloud && $organization?.billingTrialStartDate && $daysLeftInTrial > 0 && $organization.billingPlan !== BillingPlan.STARTER && $plansInfo.get($organization.billingPlan)?.trialDays}
|
||||
{#if isCloud && $organization?.billingTrialStartDate && $daysLeftInTrial > 0 && $organization.billingPlan !== BillingPlan.FREE && $plansInfo.get($organization.billingPlan)?.trialDays}
|
||||
<div
|
||||
class="u-flex u-cross-center"
|
||||
use:tooltip={{
|
||||
@@ -153,7 +153,7 @@
|
||||
<div
|
||||
use:tooltip={{
|
||||
content:
|
||||
$organization?.billingPlan === BillingPlan.STARTER
|
||||
$organization?.billingPlan === BillingPlan.FREE
|
||||
? `Upgrade to add more members`
|
||||
: `You've reached the members limit for the ${
|
||||
tierToPlan($organization?.billingPlan)?.name
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<div class="u-flex u-cross-center u-main-space-between">
|
||||
<Heading tag="h2" size="5">Usage</Heading>
|
||||
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
<Button
|
||||
href={$upgradeURL}
|
||||
on:click={() => {
|
||||
@@ -76,7 +76,7 @@
|
||||
class="link"
|
||||
type="button">Learn more about plan usage limits.</button>
|
||||
</p>
|
||||
{:else if $organization.billingPlan === BillingPlan.STARTER}
|
||||
{:else if $organization.billingPlan === BillingPlan.FREE}
|
||||
<p class="text">
|
||||
If you exceed the limits of the {plan} plan, services for your organization's projects
|
||||
may be disrupted.
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
|
||||
<p class="text">The number of members in your organization.</p>
|
||||
<svelte:fragment slot="aside">
|
||||
{#if $organization.billingPlan !== BillingPlan.STARTER}
|
||||
{#if $organization.billingPlan !== BillingPlan.FREE}
|
||||
<div class="u-flex u-flex-vertical">
|
||||
<div class="u-flex u-main-space-between">
|
||||
<p>
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
EmailTemplateLocale
|
||||
} from '@appwrite.io/console';
|
||||
import Email2FaTemplate from './email2FATemplate.svelte';
|
||||
import { tierToPlan } from '$lib/stores/billing';
|
||||
|
||||
const projectId = $page.params.project;
|
||||
|
||||
@@ -131,7 +132,7 @@
|
||||
</p>
|
||||
|
||||
<svelte:fragment slot="aside">
|
||||
{#if $organization.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization.billingPlan === BillingPlan.FREE}
|
||||
<Alert
|
||||
buttons={[
|
||||
{
|
||||
@@ -139,8 +140,8 @@
|
||||
href: `${base}/console/organization-${$organization.$id}/billing`
|
||||
}
|
||||
]}>
|
||||
All emails sent using the Starter plan will include attribution to Appwrite in
|
||||
the signature. To send attribution-free emails, upgrade your plan.
|
||||
All emails sent using the {tierToPlan(BillingPlan.FREE).name} plan will include attribution
|
||||
to Appwrite in the signature. To send attribution-free emails, upgrade your plan.
|
||||
</Alert>
|
||||
{/if}
|
||||
<Collapsible>
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@
|
||||
{hoursToDays(logs)} of logs
|
||||
</li>
|
||||
</ul>
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
<p class="text">
|
||||
<button class="link" type="button" on:click|preventDefault={upgradeMethod}
|
||||
>Upgrade</button>
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
class="link">here</a>
|
||||
</p>
|
||||
<svelte:fragment slot="aside">
|
||||
{#if $organization.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization.billingPlan === BillingPlan.FREE}
|
||||
<Alert type="info">
|
||||
Custom SMTP is a Pro plan feature. Upgrade to enable custom SMTP sever.
|
||||
<svelte:fragment slot="action">
|
||||
@@ -205,8 +205,7 @@
|
||||
<svelte:fragment slot="actions">
|
||||
<Button
|
||||
submit
|
||||
disabled={isButtonDisabled ||
|
||||
$organization.billingPlan === BillingPlan.STARTER}>
|
||||
disabled={isButtonDisabled || $organization.billingPlan === BillingPlan.FREE}>
|
||||
Update
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
<div class="u-flex u-cross-center u-main-space-between">
|
||||
<Heading tag="h2" size="5">Usage</Heading>
|
||||
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
<Button href={$upgradeURL}>
|
||||
<span class="text">Upgrade</span>
|
||||
</Button>
|
||||
@@ -71,7 +71,7 @@
|
||||
on:click={() => ($showUsageRatesModal = true)}
|
||||
link>Learn more about plan usage limits.</Button>
|
||||
</p>
|
||||
{:else if $organization.billingPlan === BillingPlan.STARTER}
|
||||
{:else if $organization.billingPlan === BillingPlan.FREE}
|
||||
<p class="text">
|
||||
If you exceed the limits of the {plan} plan, services for your projects may be disrupted.
|
||||
<a href={$upgradeURL} class="link">Upgrade for greater capacity</a>.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
PaginationWithLimit,
|
||||
SearchQuery
|
||||
} from '$lib/components';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { BillingPlan, Dependencies } from '$lib/constants';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import {
|
||||
@@ -45,7 +45,7 @@
|
||||
import { uploader } from '$lib/stores/uploader';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import { tooltip } from '$lib/actions/tooltip';
|
||||
import { getServiceLimit, showUsageRatesModal } from '$lib/stores/billing';
|
||||
import { getServiceLimit, showUsageRatesModal, tierToPlan } from '$lib/stores/billing';
|
||||
import { sdk } from '$lib/stores/sdk.js';
|
||||
import Create from './create-file/create.svelte';
|
||||
import DeleteFile from './deleteFile.svelte';
|
||||
@@ -112,7 +112,7 @@
|
||||
</SearchQuery>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="tooltip" let:limit let:tier let:upgradeMethod>
|
||||
{#if tier === 'Starter'}
|
||||
{#if tier === tierToPlan(BillingPlan.FREE).name}
|
||||
<p class="u-bold">The {tier} plan has limits</p>
|
||||
<ul>
|
||||
<li>{limit}GB total file storage</li>
|
||||
|
||||
+2
-2
@@ -27,12 +27,12 @@
|
||||
The {plan.name} plan has a maximum upload file size limit of {Math.floor(
|
||||
parseInt(size.value)
|
||||
)}{size.unit}.
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
Upgrade to allow files of a larger size.
|
||||
{/if}
|
||||
</p>
|
||||
<svelte:fragment slot="action">
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
<div class="alert-buttons u-flex">
|
||||
<Button text href={$upgradeURL}>Upgrade plan</Button>
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -41,12 +41,12 @@
|
||||
The {plan.name} plan has a maximum upload file size limit of {Math.floor(
|
||||
parseInt(size.value)
|
||||
)}{size.unit}.
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
Upgrade to allow files of a larger size.
|
||||
{/if}
|
||||
</p>
|
||||
<svelte:fragment slot="action">
|
||||
{#if $organization?.billingPlan === BillingPlan.STARTER}
|
||||
{#if $organization?.billingPlan === BillingPlan.FREE}
|
||||
<div class="alert-buttons u-flex">
|
||||
<Button text href={$upgradeURL}>Upgrade plan</Button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user