diff --git a/e2e/journeys/upgrade-free-tier.spec.ts b/e2e/journeys/upgrade-free-tier.spec.ts index 76d5fafcd..80802f499 100644 --- a/e2e/journeys/upgrade-free-tier.spec.ts +++ b/e2e/journeys/upgrade-free-tier.spec.ts @@ -11,7 +11,12 @@ test('upgrade - free tier', async ({ page }) => { await page.waitForURL(/\/organization-[^/]+\/change-plan/); await page.locator('input[value="tier-1"]').click(); await page.getByRole('button', { name: 'add' }).first().click(); + await enterCreditCard(page); + + // wait for a second after adding a card to update the UI. + await page.waitForSelector('button#method[role="combobox"]'); + // skip members await page.getByRole('button', { name: 'change plan' }).click(); await page.waitForURL(/\/console\/project-(?:[a-z0-9]+-)?([^/]+)\/get-started/); diff --git a/src/lib/components/billing/paymentModal.svelte b/src/lib/components/billing/paymentModal.svelte index 9ef191311..c79602517 100644 --- a/src/lib/components/billing/paymentModal.svelte +++ b/src/lib/components/billing/paymentModal.svelte @@ -21,7 +21,7 @@ try { const card = await submitStripeCard(name, page?.params?.organization ?? null); modal.closeModal(); - invalidate(Dependencies.PAYMENT_METHODS); + await invalidate(Dependencies.PAYMENT_METHODS); dispatch('submit', card); addNotification({ type: 'success', diff --git a/src/lib/components/billing/selectPaymentMethod.svelte b/src/lib/components/billing/selectPaymentMethod.svelte index 9a7265c8b..30e5ea254 100644 --- a/src/lib/components/billing/selectPaymentMethod.svelte +++ b/src/lib/components/billing/selectPaymentMethod.svelte @@ -20,8 +20,19 @@ async function cardSaved(event: CustomEvent) { value = event.detail.$id; - invalidate(Dependencies.UPGRADE_PLAN); - invalidate(Dependencies.CREATE_ORGANIZATION); + + if (value) { + methods = { + ...methods, + total: methods.total + 1, + paymentMethods: [...methods.paymentMethods, event.detail] + }; + } + + await Promise.all([ + invalidate(Dependencies.UPGRADE_PLAN), + invalidate(Dependencies.ORGANIZATION) + ]); } onMount(() => { diff --git a/src/lib/components/breadcrumbs.svelte b/src/lib/components/breadcrumbs.svelte index cbe0799c3..e29c4c8d0 100644 --- a/src/lib/components/breadcrumbs.svelte +++ b/src/lib/components/breadcrumbs.svelte @@ -101,7 +101,8 @@ async function createProjectsBottomSheet(organization: Organization): Promise { isLoadingProjects = true; - loadedProjects = await projects; + // null on non-org/project path like `onboarding`. + loadedProjects = (await projects) ?? loadedProjects; isLoadingProjects = false; const createProjectItem = { diff --git a/src/lib/layout/wizard.svelte b/src/lib/layout/wizard.svelte index 3cf61a924..8a0d696b0 100644 --- a/src/lib/layout/wizard.svelte +++ b/src/lib/layout/wizard.svelte @@ -50,7 +50,7 @@ if (confirmExit) { showExitModal = true; } else { - goto(href); + goBack(); trackEvent('wizard_exit', { from: 'escape' }); @@ -58,6 +58,8 @@ } } + const goBack = () => goto(href); + onMount(() => ($isNewWizardStatusOpen = true)); onDestroy(() => ($isNewWizardStatusOpen = false)); @@ -77,7 +79,7 @@ if (confirmExit) { showExitModal = true; } else { - goto(href); + goBack(); trackEvent('wizard_exit', { from: 'button' }); diff --git a/src/routes/(console)/+layout.svelte b/src/routes/(console)/+layout.svelte index 4a6d3ac3b..452847d49 100644 --- a/src/routes/(console)/+layout.svelte +++ b/src/routes/(console)/+layout.svelte @@ -316,15 +316,19 @@ $: checkForUsageLimits($organization); - $: projects = sdk.forConsole.projects.list([ - Query.equal( - 'teamId', - // id from page params ?? id from store ?? id from preferences - page.params.organization ?? currentOrganizationId ?? data.currentOrgId - ), - Query.limit(5), - Query.orderDesc('$updatedAt') - ]); + $: isOnOnboarding = page.route?.id?.includes('/(console)/onboarding'); + + $: projects = isOnOnboarding + ? null + : sdk.forConsole.projects.list([ + Query.equal( + 'teamId', + // id from page params ?? id from store ?? id from preferences + page.params.organization ?? currentOrganizationId ?? data.currentOrgId + ), + Query.limit(5), + Query.orderDesc('$updatedAt') + ]); $: if ($requestedMigration) { openMigrationWizard(); diff --git a/src/routes/(console)/create-organization/+page.ts b/src/routes/(console)/create-organization/+page.ts index f6f9eeb7f..9aba3aefd 100644 --- a/src/routes/(console)/create-organization/+page.ts +++ b/src/routes/(console)/create-organization/+page.ts @@ -5,8 +5,9 @@ import type { Coupon } from '$lib/sdk/billing'; import type { Organization } from '$lib/stores/organization'; export const load: PageLoad = async ({ url, parent, depends }) => { - depends(Dependencies.CREATE_ORGANIZATION); const { organizations } = await parent(); + depends(Dependencies.CREATE_ORGANIZATION); + const [coupon, paymentMethods] = await Promise.all([ getCoupon(url), sdk.forConsole.billing.listPaymentMethods() diff --git a/src/routes/(console)/onboarding/create-organization/+page.svelte b/src/routes/(console)/onboarding/create-organization/+page.svelte index 0118c0e3c..73524af47 100644 --- a/src/routes/(console)/onboarding/create-organization/+page.svelte +++ b/src/routes/(console)/onboarding/create-organization/+page.svelte @@ -2,14 +2,14 @@ import { isCloud } from '$lib/system'; import { sdk } from '$lib/stores/sdk'; import { ID } from '@appwrite.io/console'; - import { BillingPlan } from '$lib/constants'; + import { BillingPlan, Dependencies } from '$lib/constants'; import { tierToPlan } from '$lib/stores/billing'; import { addNotification } from '$lib/stores/notifications'; import { loadAvailableRegions } from '$routes/(console)/regions'; import { Submit, trackError, trackEvent } from '$lib/actions/analytics'; import { Button, Card, Layout, Input, Typography, Spinner } from '@appwrite.io/pink-svelte'; import { Form } from '$lib/elements/forms/index.js'; - import { goto } from '$app/navigation'; + import { goto, invalidate } from '$app/navigation'; import { base } from '$app/paths'; let isLoading = false; @@ -47,6 +47,10 @@ if (organization) { loadAvailableRegions(organization?.$id).then(); await goto(`${base}/organization-${organization.$id}`); + + // fixes an edge case where + // the org is not available for some reason! + await invalidate(Dependencies.CREATE_ORGANIZATION); } isLoading = false; } diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index f31095d81..e0bc8eb0c 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -271,11 +271,7 @@ Change plan - Appwrite - +
@@ -338,12 +334,12 @@
- {:then paymentMethods} + {:then}
+ bind:methods={paymentMethods}> {#if !selectedCoupon?.code} {#if paymentMethodId} diff --git a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/totalMembers.svelte b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/totalMembers.svelte index 1609ddbf6..15176735f 100644 --- a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/totalMembers.svelte +++ b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/totalMembers.svelte @@ -52,7 +52,7 @@ - + {#snippet children(paginatedItems: typeof members.memberships)} diff --git a/src/routes/(console)/project-[region]-[project]/auth/security/updateSessionLength.svelte b/src/routes/(console)/project-[region]-[project]/auth/security/updateSessionLength.svelte index 14edb541c..295ce51c6 100644 --- a/src/routes/(console)/project-[region]-[project]/auth/security/updateSessionLength.svelte +++ b/src/routes/(console)/project-[region]-[project]/auth/security/updateSessionLength.svelte @@ -7,11 +7,13 @@ import { createTimeUnitPair } from '$lib/helpers/unit'; import { addNotification } from '$lib/stores/notifications'; import { sdk } from '$lib/stores/sdk'; - import { project } from '../../store'; + import { project as projectStore } from '../../store'; import { Layout } from '@appwrite.io/pink-svelte'; + import { page } from '$app/state'; - const { value, unit, baseValue, units } = createTimeUnitPair($project?.authDuration); - const options = units.map((v) => ({ label: v.name, value: v.name })); + const project = $derived($projectStore ?? page.data?.project); + const { value, unit, baseValue, units } = $derived(createTimeUnitPair(project?.authDuration)); + const options = $derived(units.map((v) => ({ label: v.name, value: v.name }))); async function updateSessionLength() { try { @@ -43,7 +45,7 @@ - diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 78d86d2e4..21fe42dde 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -16,6 +16,7 @@ export const ssr = false; export const load: LayoutLoad = async ({ depends, url, route }) => { depends(Dependencies.ACCOUNT); + depends(Dependencies.CREATE_ORGANIZATION); const [account, error] = (await sdk.forConsole.account .get()