Skip to content

Commit fee67a1

Browse files
authored
Merge pull request #2722 from appwrite/billing-sdk-refactor
2 parents e56ee59 + c896248 commit fee67a1

File tree

218 files changed

+2912
-4162
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

218 files changed

+2912
-4162
lines changed

e2e/steps/free-project.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,15 @@ export async function createFreeProject(page: Page): Promise<Metadata> {
2424
const regionPicker = dialog.locator('button[role="combobox"]');
2525
if (await regionPicker.isVisible()) {
2626
await regionPicker.click();
27-
await page.getByRole('option', { name: /New York/i }).click();
28-
29-
region = 'nyc';
27+
const firstEnabledOption = page
28+
.locator('[role="option"]:not([data-disabled="true"])')
29+
.first();
30+
31+
if ((await firstEnabledOption.count()) > 0) {
32+
const selectedRegion = await firstEnabledOption.getAttribute('data-value');
33+
await firstEnabledOption.click();
34+
region = selectedRegion?.replace(/"/g, '') || 'fra';
35+
}
3036
}
3137

3238
await dialog.getByRole('button', { name: 'create' }).click();

e2e/steps/pro-project.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,15 @@ export async function createProProject(page: Page): Promise<Metadata> {
5757
const regionPicker = dialog.locator('button[role="combobox"]');
5858
if (await regionPicker.isVisible()) {
5959
await regionPicker.click();
60-
await page.getByRole('option', { name: /New York/i }).click();
60+
const firstEnabledOption = page
61+
.locator('[role="option"]:not([data-disabled="true"])')
62+
.first();
6163

62-
region = 'nyc';
64+
if ((await firstEnabledOption.count()) > 0) {
65+
const selectedRegion = await firstEnabledOption.getAttribute('data-value');
66+
await firstEnabledOption.click();
67+
region = selectedRegion?.replace(/"/g, '') || 'fra';
68+
}
6369
}
6470

6571
await dialog.getByRole('button', { name: 'create' }).click();

src/lib/commandCenter/searchers/organizations.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
1+
import { resolve } from '$app/paths';
12
import { goto } from '$app/navigation';
2-
import { base } from '$app/paths';
3-
import { sdk } from '$lib/stores/sdk';
43
import type { Searcher } from '../commands';
5-
import { isCloud } from '$lib/system';
6-
import { Platform, Query } from '@appwrite.io/console';
4+
import { getTeamOrOrganizationList } from '$lib/stores/organization';
75

86
export const orgSearcher = (async (query: string) => {
9-
const { teams } = !isCloud
10-
? await sdk.forConsole.teams.list()
11-
: await sdk.forConsole.billing.listOrganization([
12-
Query.equal('platform', Platform.Appwrite)
13-
]);
7+
const { teams } = await getTeamOrOrganizationList();
148

159
return teams
1610
.filter((organization) => organization.name.toLowerCase().includes(query.toLowerCase()))
1711
.map((organization) => {
1812
return {
1913
label: organization.name,
2014
callback: () => {
21-
goto(`${base}/organization-${organization.$id}`);
15+
goto(
16+
resolve('/(console)/organization-[organization]', {
17+
organization: organization.$id
18+
})
19+
);
2220
},
2321
group: 'organizations'
2422
} as const;

src/lib/components/archiveProject.svelte

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,21 @@
3838
import { isSmallViewport } from '$lib/stores/viewport';
3939
import { isCloud } from '$lib/system';
4040
import { regions as regionsStore } from '$lib/stores/organization';
41-
import type { Organization } from '$lib/stores/organization';
42-
import type { Plan } from '$lib/sdk/billing';
4341
4442
// props
4543
interface Props {
44+
currentPlan: Models.BillingPlan;
45+
organization: Models.Organization;
4646
projectsToArchive: Models.Project[];
47-
organization: Organization;
48-
currentPlan: Plan;
4947
archivedTotalOverall: number;
5048
archivedOffset: number;
5149
limit: number;
5250
}
5351
5452
let {
55-
projectsToArchive,
56-
organization,
5753
currentPlan,
54+
organization,
55+
projectsToArchive,
5856
archivedTotalOverall,
5957
archivedOffset,
6058
limit

src/lib/components/backupDatabaseAlert.svelte

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
<script lang="ts">
22
import { page } from '$app/state';
3-
import { BillingPlan } from '$lib/constants';
43
import { Button } from '$lib/elements/forms';
54
import { organization } from '$lib/stores/organization';
65
import { HeaderAlert } from '$lib/layout';
76
import { isCloud } from '$lib/system';
8-
import { upgradeURL } from '$lib/stores/billing';
7+
import { getChangePlanUrl } from '$lib/stores/billing';
98
import { hideNotification } from '$lib/helpers/notifications';
109
import { backupsBannerId, showPolicyAlert } from '$lib/stores/database';
1110
import { IconX } from '@appwrite.io/pink-icons-svelte';
@@ -18,14 +17,16 @@
1817
</script>
1918

2019
{#if $showPolicyAlert && isCloud && $organization?.$id && page.url.pathname.match(/\/databases\/database-[^/]+$/)}
21-
{@const isFreePlan = $organization?.billingPlan === BillingPlan.FREE}
20+
{@const areBackupsAvailable = $organization?.billingPlanDetails.backupsEnabled}
2221

23-
{@const subtitle = isFreePlan
22+
{@const subtitle = !areBackupsAvailable
2423
? 'Upgrade your plan to ensure your data stays safe and backed up'
2524
: 'Protect your data by quickly adding a backup policy'}
2625

27-
{@const ctaText = isFreePlan ? 'Upgrade plan' : 'Create policy'}
28-
{@const ctaURL = isFreePlan ? $upgradeURL : `${page.url.pathname}/backups`}
26+
{@const ctaText = !areBackupsAvailable ? 'Upgrade plan' : 'Create policy'}
27+
{@const ctaURL = !areBackupsAvailable
28+
? getChangePlanUrl($organization.$id)
29+
: `${page.url.pathname}/backups`}
2930

3031
<HeaderAlert type="warning" title="Your database has no backup policy">
3132
<svelte:fragment>{subtitle}</svelte:fragment>
@@ -35,7 +36,7 @@
3536
href={ctaURL}
3637
secondary
3738
fullWidthMobile
38-
event={isFreePlan ? 'backup_banner_upgrade' : 'backup_banner_add'}>
39+
event={!areBackupsAvailable ? 'backup_banner_upgrade' : 'backup_banner_add'}>
3940
<span class="text">{ctaText}</span>
4041
</Button>
4142

src/lib/components/backupRestoreBox.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import { onMount } from 'svelte';
55
import { isCloud, isSelfHosted } from '$lib/system';
66
import { organization } from '$lib/stores/organization';
7-
import { BillingPlan, Dependencies } from '$lib/constants';
7+
import { Dependencies } from '$lib/constants';
88
import { goto, invalidate } from '$app/navigation';
99
import { page } from '$app/state';
1010
import { addNotification } from '$lib/stores/notifications';
@@ -125,8 +125,8 @@
125125
}
126126
127127
onMount(() => {
128-
// fast path: don't subscribe if org is on a free plan or is self-hosted.
129-
if (isSelfHosted || (isCloud && $organization?.billingPlan === BillingPlan.FREE)) return;
128+
// fast path: don't subscribe if org doesn't support backups or is self-hosted.
129+
if (isSelfHosted || (isCloud && !$organization?.billingPlanDetails.backupsEnabled)) return;
130130
131131
return realtime.forProject(page.params.region, 'console', (response) => {
132132
if (!response.channels.includes(`projects.${getProjectId()}`)) return;

src/lib/components/billing/alerts/limitReached.svelte

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,19 @@
22
import { base } from '$app/paths';
33
import { page } from '$app/state';
44
import { Click, trackEvent } from '$lib/actions/analytics';
5-
import { BillingPlan } from '$lib/constants';
65
import { Button } from '$lib/elements/forms';
76
import { HeaderAlert } from '$lib/layout';
8-
import { hideBillingHeaderRoutes, readOnly, tierToPlan, upgradeURL } from '$lib/stores/billing';
7+
import { hideBillingHeaderRoutes, readOnly, getChangePlanUrl } from '$lib/stores/billing';
98
import { organization } from '$lib/stores/organization';
109
</script>
1110

12-
{#if $organization?.$id && $organization?.billingPlan === BillingPlan.FREE && $readOnly && !hideBillingHeaderRoutes.includes(page.url.pathname)}
11+
{#if $organization?.$id && !$organization?.billingPlanDetails.usage && $readOnly && !hideBillingHeaderRoutes.includes(page.url.pathname)}
1312
<HeaderAlert
1413
type="error"
15-
title={`${$organization.name} usage has reached the ${tierToPlan($organization.billingPlan).name} plan limit`}>
14+
title={`${$organization.name} usage has reached the ${$organization.billingPlanDetails.name} plan limit`}>
1615
<svelte:fragment>
17-
Usage for the <b>{$organization.name}</b> organization has reached the limits of the {tierToPlan(
18-
$organization.billingPlan
19-
).name}
16+
Usage for the <b>{$organization.name}</b> organization has reached the limits of the {$organization
17+
.billingPlanDetails.name}
2018
plan. Consider upgrading to increase your resource usage.
2119
</svelte:fragment>
2220
<svelte:fragment slot="buttons">
@@ -29,7 +27,7 @@
2927
</Button>
3028
{/if}
3129
<Button
32-
href={$upgradeURL}
30+
href={getChangePlanUrl($organization.$id)}
3331
on:click={() => {
3432
trackEvent(Click.OrganizationClickUpgrade, {
3533
from: 'button',

src/lib/components/billing/alerts/missingPaymentMethod.svelte

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,36 @@
11
<script lang="ts">
22
import { base } from '$app/paths';
33
import { page } from '$app/state';
4-
import { BillingPlan } from '$lib/constants';
54
import { Button } from '$lib/elements/forms';
65
import { HeaderAlert } from '$lib/layout';
76
import { hideBillingHeaderRoutes } from '$lib/stores/billing';
87
import { orgMissingPaymentMethod } from '$routes/(console)/store';
8+
9+
// exists
10+
$: hasOrgBillingContext = !!$orgMissingPaymentMethod;
11+
12+
// needs any methods
13+
$: requiresPaymentMethod =
14+
hasOrgBillingContext && $orgMissingPaymentMethod.billingPlanDetails.requiresPaymentMethod;
15+
16+
// has any methods
17+
$: hasAnyPaymentMethod =
18+
hasOrgBillingContext &&
19+
(!!$orgMissingPaymentMethod.paymentMethodId ||
20+
!!$orgMissingPaymentMethod.backupPaymentMethodId);
21+
22+
// is url excluded
23+
$: isBillingHeaderHidden = hideBillingHeaderRoutes.includes(page.url.pathname);
24+
25+
// should show header
26+
$: shouldShowBillingHeader =
27+
hasOrgBillingContext &&
28+
requiresPaymentMethod &&
29+
!hasAnyPaymentMethod &&
30+
!isBillingHeaderHidden;
931
</script>
1032

11-
{#if ($orgMissingPaymentMethod.billingPlan === BillingPlan.PRO || $orgMissingPaymentMethod.billingPlan === BillingPlan.SCALE) && !$orgMissingPaymentMethod.paymentMethodId && !$orgMissingPaymentMethod.backupPaymentMethodId && !hideBillingHeaderRoutes.includes(page.url.pathname)}
33+
{#if shouldShowBillingHeader}
1234
<HeaderAlert
1335
type="error"
1436
title={`Payment method required for ${$orgMissingPaymentMethod.name}`}>

src/lib/components/billing/alerts/newDevUpgradePro.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { base } from '$app/paths';
33
import { page } from '$app/state';
44
import { Click, trackEvent } from '$lib/actions/analytics';
5-
import { BillingPlan, NEW_DEV_PRO_UPGRADE_COUPON } from '$lib/constants';
5+
import { NEW_DEV_PRO_UPGRADE_COUPON } from '$lib/constants';
66
import { Button } from '$lib/elements/forms';
77
import { organization } from '$lib/stores/organization';
88
import { activeHeaderAlert } from '$routes/(console)/store';
@@ -23,7 +23,7 @@
2323
}
2424
</script>
2525

26-
{#if show && $organization?.$id && $organization?.billingPlan === BillingPlan.FREE && !page.url.pathname.includes(base + '/account')}
26+
{#if show && $organization?.$id && !$organization?.billingPlanDetails.supportsCredits && !page.url.pathname.includes(base + '/account')}
2727
<GradientBanner on:close={handleClose}>
2828
<Layout.Stack
2929
gap="m"

src/lib/components/billing/alerts/projectsLimit.svelte

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { Click } from '$lib/actions/analytics';
44
import { Button } from '$lib/elements/forms';
55
import { HeaderAlert } from '$lib/layout';
6-
import { hideBillingHeaderRoutes, upgradeURL } from '$lib/stores/billing';
6+
import { hideBillingHeaderRoutes, getChangePlanUrl } from '$lib/stores/billing';
77
import { currentPlan, organization } from '$lib/stores/organization';
88
import SelectProjectCloud from './selectProjectCloud.svelte';
99
import { toLocaleDate } from '$lib/helpers/date';
@@ -22,7 +22,7 @@
2222

2323
<SelectProjectCloud bind:showSelectProject bind:selectedProjects {organizationId} />
2424

25-
{#if $currentPlan && $currentPlan.projects > 0 && !hideBillingHeaderRoutes.includes(page.url.pathname)}
25+
{#if organizationId && $currentPlan && $currentPlan.projects > 0 && !hideBillingHeaderRoutes.includes(page.url.pathname)}
2626
<HeaderAlert
2727
type="warning"
2828
title="Action required: You have more than {$currentPlan.projects} projects.">
@@ -38,7 +38,7 @@
3838
showSelectProject = true;
3939
}}>Manage projects</Button>
4040
<Button
41-
href={$upgradeURL}
41+
href={getChangePlanUrl(organizationId)}
4242
event={Click.OrganizationClickUpgrade}
4343
eventData={{
4444
from: 'button',

0 commit comments

Comments
 (0)