From f94d9cc94c2af4671c7e559fbefd850d22eb5eb6 Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 27 Dec 2023 18:19:37 +0100 Subject: [PATCH 01/46] feat: create new billing endpoints --- src/lib/sdk/billing.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index 8773bb77b..156a259e4 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -702,6 +702,46 @@ export class Billing { ); } + async getOrganizationPaymentMethod( + organizationId: string, + paymentMethodId: string + ): Promise { + const path = `/organizations/${organizationId}/payment-methods/${paymentMethodId}`; + const params = { + organizationId, + paymentMethodId + }; + const uri = new URL(this.client.config.endpoint + path); + return await this.client.call( + 'GET', + uri, + { + 'content-type': 'application/json' + }, + params + ); + } + + async getOrganizationBillingAddress( + organizationId: string, + billingAddressId: string + ): Promise { + const path = `/organizations/${organizationId}/payment-methods/${billingAddressId}`; + const params = { + organizationId, + billingAddressId + }; + const uri = new URL(this.client.config.endpoint + path); + return await this.client.call( + 'GET', + uri, + { + 'content-type': 'application/json' + }, + params + ); + } + //ACCOUNT async listPaymentMethods(queries: [] = []): Promise { From 3646c6a9acacbfe72d05c3a3014b71392d2c69bc Mon Sep 17 00:00:00 2001 From: Arman Date: Fri, 29 Dec 2023 19:45:45 +0100 Subject: [PATCH 02/46] feat: replace methods? --- src/lib/stores/billing.ts | 5 ++++- .../billing/paymentMethods.svelte | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index 190db1234..f27e46dcc 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -211,7 +211,10 @@ export async function checkPaymentAuthorizationRequired(org: Organization) { export async function paymentExpired(org: Organization) { if (!org?.paymentMethodId) return; - const payment = await sdk.forConsole.billing.getPaymentMethod(org.paymentMethodId); + const payment = await sdk.forConsole.billing.getOrganizationPaymentMethod( + org.$id, + org.paymentMethodId + ); if (!payment?.expiryYear) return; const year = new Date().getFullYear(); const month = new Date().getMonth(); diff --git a/src/routes/console/organization-[organization]/billing/paymentMethods.svelte b/src/routes/console/organization-[organization]/billing/paymentMethods.svelte index ae44de05e..8936783a7 100644 --- a/src/routes/console/organization-[organization]/billing/paymentMethods.svelte +++ b/src/routes/console/organization-[organization]/billing/paymentMethods.svelte @@ -77,13 +77,13 @@ $: if ($organization?.backupPaymentMethodId) { sdk.forConsole.billing - .getPaymentMethod($organization.backupPaymentMethodId) + .getOrganizationPaymentMethod($organization.$id, $organization.backupPaymentMethodId) .then((res) => (backupPaymentMethod = res)); } $: if ($organization?.paymentMethodId) { sdk.forConsole.billing - .getPaymentMethod($organization.paymentMethodId) + .getOrganizationPaymentMethod($organization.$id, $organization.paymentMethodId) .then((res) => (defaultPaymentMethod = res)); } From 196d229a7aaa2b69d0f8ba2e0c082bccacd61fef Mon Sep 17 00:00:00 2001 From: Arman Date: Mon, 12 Feb 2024 11:13:13 +0100 Subject: [PATCH 03/46] fix: endpoint --- src/lib/sdk/billing.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index e36518cd6..760e18b48 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -750,7 +750,7 @@ export class Billing { organizationId: string, billingAddressId: string ): Promise { - const path = `/organizations/${organizationId}/payment-methods/${billingAddressId}`; + const path = `/organizations/${organizationId}/billing-addresses/${billingAddressId}`; const params = { organizationId, billingAddressId From 56cc9ee9eeae2cb5be7022fc20e3961330cede3d Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 20 Mar 2024 14:58:07 +0100 Subject: [PATCH 04/46] feat: add invoice last error --- src/lib/sdk/billing.ts | 1 + .../billing/+page.svelte | 20 ++++--- .../billing/paymentHistory.svelte | 58 +++++++++++++++---- 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index 60165d453..687ed4c4a 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -48,6 +48,7 @@ export type Invoice = { rate: number; desc: string; }[]; + lastError?: string; }; export type InvoiceList = { diff --git a/src/routes/console/organization-[organization]/billing/+page.svelte b/src/routes/console/organization-[organization]/billing/+page.svelte index 379814dd1..15d12017a 100644 --- a/src/routes/console/organization-[organization]/billing/+page.svelte +++ b/src/routes/console/organization-[organization]/billing/+page.svelte @@ -76,13 +76,19 @@ {#if $failedInvoice} - - - The scheduled payment for {$organization.name} failed - - To avoid service disruptions in organization's your projects, please verify your payment - details and update them if necessary. - + {#if $failedInvoice?.lastError} + + The scheduled payment for {$organization.name} failed due to following error: {$failedInvoice.lastError} + + {:else} + + + The scheduled payment for {$organization.name} failed + + To avoid service disruptions in organization's your projects, please verify your payment + details and update them if necessary. + + {/if} {/if} {#if defaultPaymentMethod?.failed && !backupPaymentMethod} diff --git a/src/routes/console/organization-[organization]/billing/paymentHistory.svelte b/src/routes/console/organization-[organization]/billing/paymentHistory.svelte index a8caf4348..8339ac60b 100644 --- a/src/routes/console/organization-[organization]/billing/paymentHistory.svelte +++ b/src/routes/console/organization-[organization]/billing/paymentHistory.svelte @@ -22,7 +22,7 @@ } from '$lib/elements/table'; import { toLocaleDate } from '$lib/helpers/date'; import { formatCurrency } from '$lib/helpers/numbers'; - import type { InvoiceList } from '$lib/sdk/billing'; + import type { Invoice, InvoiceList } from '$lib/sdk/billing'; import { sdk } from '$lib/stores/sdk'; import { VARS } from '$lib/system'; import { Query } from '@appwrite.io/console'; @@ -31,6 +31,7 @@ import { selectedInvoice, showRetryModal } from './store'; let showDropdown = []; + let showFailedError = false; let offset = 0; let invoiceList: InvoiceList = { @@ -51,6 +52,11 @@ ]); } + function retryPayment(invoice: Invoice) { + $selectedInvoice = invoice; + $showRetryModal = true; + } + $: if (offset !== null) { request(); } @@ -82,14 +88,45 @@ - - {status === 'requires_authentication' ? 'failed' : status} - + {#if invoice?.lastError} + + (showFailedError = true)} + button> + {status === 'requires_authentication' + ? 'failed' + : status} + + +
  • + The scheduled payment has failed. . +
  • +
    +
    + {:else} + + {status === 'requires_authentication' + ? 'failed' + : status} + + {/if}
    {formatCurrency(invoice.amount)} @@ -132,8 +169,7 @@ { - $selectedInvoice = invoice; - $showRetryModal = true; + retryPayment(invoice); showDropdown[i] = !showDropdown[i]; trackEvent(`click_retry_payment`, { from: 'button', From c9763b6810d714852a17e3bcd023b881b3b3458a Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 20 Mar 2024 16:33:50 +0100 Subject: [PATCH 05/46] feat: invoice alert --- src/lib/stores/billing.ts | 8 ++++---- .../organization-[organization]/billing/+page.svelte | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index c213a7147..f577abd94 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -77,18 +77,18 @@ export function getServiceLimit(serviceId: PlanServices, tier: Tier = null): num } export const failedInvoice = cachedStore< - false | Invoice, + Invoice, { load: (orgId: string) => Promise; } >('failedInvoice', function ({ set }) { return { load: async (orgId) => { - if (!isCloud) set(false); + if (!isCloud) set(null); const invoices = await sdk.forConsole.billing.listInvoices(orgId); const failedInvoices = invoices.invoices.filter((i) => i.status === 'failed'); // const failedInvoices = invoices.invoices; - if (failedInvoices.length > 0) { + if (failedInvoices?.length > 0) { const firstFailed = failedInvoices[0]; const today = new Date(); const thirtyDaysAgo = new Date(today.setDate(today.getDate() - 30)); @@ -96,7 +96,7 @@ export const failedInvoice = cachedStore< if (failedDate < thirtyDaysAgo) { readOnly.set(true); } - } else set(false); + } else set(null); } }; }); diff --git a/src/routes/console/organization-[organization]/billing/+page.svelte b/src/routes/console/organization-[organization]/billing/+page.svelte index 15d12017a..c437fd53f 100644 --- a/src/routes/console/organization-[organization]/billing/+page.svelte +++ b/src/routes/console/organization-[organization]/billing/+page.svelte @@ -22,6 +22,7 @@ import { BillingPlan } from '$lib/constants'; import RetryPaymentModal from './retryPaymentModal.svelte'; import { selectedInvoice, showRetryModal } from './store'; + import { Button } from '$lib/elements/forms'; $: defaultPaymentMethod = $paymentMethods?.paymentMethods?.find( (method: PaymentMethodData) => method.$id === $organization?.paymentMethodId @@ -79,6 +80,14 @@ {#if $failedInvoice?.lastError} The scheduled payment for {$organization.name} failed due to following error: {$failedInvoice.lastError} + + + {:else} From 589ad86048f38fbc891e7056a05b2809191276b7 Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 20 Mar 2024 17:53:53 +0100 Subject: [PATCH 06/46] feat: add alert to payment method --- src/lib/components/creditCardInfo.svelte | 5 +++++ src/lib/sdk/billing.ts | 1 + 2 files changed, 6 insertions(+) diff --git a/src/lib/components/creditCardInfo.svelte b/src/lib/components/creditCardInfo.svelte index b3b89d0d7..fdbd08abe 100644 --- a/src/lib/components/creditCardInfo.svelte +++ b/src/lib/components/creditCardInfo.svelte @@ -33,4 +33,9 @@ This payment method has expired {/if} + {#if paymentMethod?.lastError} + + {paymentMethod.lastError} + + {/if} diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index 687ed4c4a..d935bd84e 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -19,6 +19,7 @@ export type PaymentMethodData = { failed: boolean; name: string; mandateId?: string; + lastError?: string; }; export type PaymentList = { From 9cd02d9dd3b5c0160b2e710e9939c52270a2df6b Mon Sep 17 00:00:00 2001 From: Arman Date: Thu, 21 Mar 2024 14:11:51 +0100 Subject: [PATCH 07/46] chore: use new method to fetch address --- src/lib/sdk/billing.ts | 2 +- .../billing/+page.svelte | 4 +++- .../organization-[organization]/billing/+page.ts | 14 +++++++++++++- .../billing/billingAddress.svelte | 7 +++---- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index 570308fc2..21173b191 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -766,7 +766,7 @@ export class Billing { async getOrganizationBillingAddress( organizationId: string, billingAddressId: string - ): Promise { + ): Promise
    { const path = `/organizations/${organizationId}/billing-addresses/${billingAddressId}`; const params = { organizationId, diff --git a/src/routes/console/organization-[organization]/billing/+page.svelte b/src/routes/console/organization-[organization]/billing/+page.svelte index 379814dd1..cee7c3a1d 100644 --- a/src/routes/console/organization-[organization]/billing/+page.svelte +++ b/src/routes/console/organization-[organization]/billing/+page.svelte @@ -23,6 +23,8 @@ import RetryPaymentModal from './retryPaymentModal.svelte'; import { selectedInvoice, showRetryModal } from './store'; + export let data; + $: defaultPaymentMethod = $paymentMethods?.paymentMethods?.find( (method: PaymentMethodData) => method.$id === $organization?.paymentMethodId ); @@ -106,7 +108,7 @@ - + {#if $organization?.billingPlan !== BillingPlan.STARTER && !!$organization?.billingBudget} diff --git a/src/routes/console/organization-[organization]/billing/+page.ts b/src/routes/console/organization-[organization]/billing/+page.ts index a1eb3b685..40f5407d0 100644 --- a/src/routes/console/organization-[organization]/billing/+page.ts +++ b/src/routes/console/organization-[organization]/billing/+page.ts @@ -1,4 +1,6 @@ import { Dependencies } from '$lib/constants'; +import type { Address } from '$lib/sdk/billing'; +import type { Organization } from '$lib/stores/organization'; import { sdk } from '$lib/stores/sdk'; import type { PageLoad } from './$types'; @@ -10,9 +12,19 @@ export const load: PageLoad = async ({ parent, depends }) => { depends(Dependencies.INVOICES); depends(Dependencies.ADDRESS); + let billingAddress: Address = null; + const billingAddressId = (organization as Organization)?.billingAddressId; + if (billingAddressId) { + billingAddress = await sdk.forConsole.billing.getOrganizationBillingAddress( + organization.$id, + billingAddressId + ); + } + return { paymentMethods: await sdk.forConsole.billing.listPaymentMethods(), addressList: await sdk.forConsole.billing.listAddresses(), - aggregationList: await sdk.forConsole.billing.listAggregation(organization.$id) + aggregationList: await sdk.forConsole.billing.listAggregation(organization.$id), + billingAddress }; }; diff --git a/src/routes/console/organization-[organization]/billing/billingAddress.svelte b/src/routes/console/organization-[organization]/billing/billingAddress.svelte index aa432851b..06036d124 100644 --- a/src/routes/console/organization-[organization]/billing/billingAddress.svelte +++ b/src/routes/console/organization-[organization]/billing/billingAddress.svelte @@ -5,6 +5,7 @@ import DropListItem from '$lib/components/dropListItem.svelte'; import { Dependencies } from '$lib/constants'; import { Button } from '$lib/elements/forms'; + import type { Address } from '$lib/sdk/billing'; import { addressList } from '$lib/stores/billing'; import { addNotification } from '$lib/stores/notifications'; import { organization } from '$lib/stores/organization'; @@ -13,6 +14,8 @@ import EditAddressModal from '$routes/console/account/payments/editAddressModal.svelte'; import ReplaceAddress from './replaceAddress.svelte'; + export let billingAddress: Address = null; + let showDropdown = false; let showBillingAddressDropdown = false; let showCreate = false; @@ -40,10 +43,6 @@ trackError(error, Submit.OrganizationBillingAddressUpdate); } } - - $: billingAddress = $addressList?.billingAddresses?.find( - (address) => address.$id === $organization?.billingAddressId - ); From 92c7f43888366b6935025a7d8ccc8fc38b283522 Mon Sep 17 00:00:00 2001 From: Arman Date: Thu, 21 Mar 2024 17:57:19 +0100 Subject: [PATCH 08/46] feat: trial changes --- src/lib/stores/billing.ts | 3 ++- src/lib/system.ts | 1 + src/routes/console/account/organizations/+page.svelte | 4 ++-- .../billing/planSummary.svelte | 5 +++-- .../console/organization-[organization]/header.svelte | 4 ++-- .../wizard/cloudOrganization/confirmDetails.svelte | 11 +++++++---- .../cloudOrganization/organizationDetails.svelte | 6 ++++-- .../wizard/cloudOrganization/paymentDetails.svelte | 7 ++++--- src/routes/console/wizard/cloudOrganization/store.ts | 5 ++++- .../cloudOrganizationChangeTier/choosePlan.svelte | 3 ++- .../cloudOrganizationChangeTier/confirmDetails.svelte | 11 +++++++---- .../wizard/cloudOrganizationChangeTier/store.ts | 5 ++++- 12 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index c213a7147..3d684f0af 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -10,7 +10,7 @@ import type { PlansMap, PaymentMethodData } from '$lib/sdk/billing'; -import { isCloud } from '$lib/system'; +import { TRIAL_PERIOD_OVERRIDE, isCloud } from '$lib/system'; import { cachedStore } from '$lib/helpers/cache'; import { Query } from '@appwrite.io/console'; import { headerAlert } from './headerAlert'; @@ -165,6 +165,7 @@ export function isServiceLimited(serviceId: PlanServices, plan: Tier, total: num } export function calculateTrialDay(org: Organization) { + if (TRIAL_PERIOD_OVERRIDE) return; if (org?.billingPlan === BillingPlan.STARTER) return false; const endDate = new Date(org?.billingStartDate); const today = new Date(); diff --git a/src/lib/system.ts b/src/lib/system.ts index 5cb998dca..521833161 100644 --- a/src/lib/system.ts +++ b/src/lib/system.ts @@ -24,3 +24,4 @@ export const isCloud = MODE === Mode.CLOUD; export const isSelfHosted = MODE !== Mode.CLOUD; export const hasStripePublicKey = !!VARS.STRIPE_PUBLIC_KEY; export const GRACE_PERIOD_OVERRIDE = false; +export const TRIAL_PERIOD_OVERRIDE = true; diff --git a/src/routes/console/account/organizations/+page.svelte b/src/routes/console/account/organizations/+page.svelte index 0216b5621..33b397915 100644 --- a/src/routes/console/account/organizations/+page.svelte +++ b/src/routes/console/account/organizations/+page.svelte @@ -13,7 +13,7 @@ import CreateOrganization from '../../createOrganization.svelte'; import { sdk } from '$lib/stores/sdk'; import type { PageData } from './$types'; - import { isCloud } from '$lib/system'; + import { TRIAL_PERIOD_OVERRIDE, isCloud } from '$lib/system'; import { Pill } from '$lib/elements'; import type { Models } from '@appwrite.io/console'; import type { Organization } from '$lib/stores/organization'; @@ -82,7 +82,7 @@ FREE {/if} - {#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.STARTER} + {#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.STARTER && !TRIAL_PERIOD_OVERRIDE}
    0; + $: isTrial = (new Date($organization?.billingStartDate).getTime() - today.getTime() > 0 ) && !TRIAL_PERIOD_OVERRIDE; {#if $organization} @@ -53,7 +54,7 @@
    {tierToPlan($organization?.billingPlan)?.name} plan
    - {#if $organization?.billingPlan !== BillingPlan.STARTER && isTrial} + {#if $organization?.billingPlan !== BillingPlan.STARTER && isTrial && } TRIAL {/if}
    diff --git a/src/routes/console/organization-[organization]/header.svelte b/src/routes/console/organization-[organization]/header.svelte index f0eb26049..04213a412 100644 --- a/src/routes/console/organization-[organization]/header.svelte +++ b/src/routes/console/organization-[organization]/header.svelte @@ -18,7 +18,7 @@ organizationList } from '$lib/stores/organization'; import { wizard } from '$lib/stores/wizard'; - import { GRACE_PERIOD_OVERRIDE, isCloud } from '$lib/system'; + import { GRACE_PERIOD_OVERRIDE, TRIAL_PERIOD_OVERRIDE, isCloud } from '$lib/system'; import CreateOrganizationCloud from '../createOrganizationCloud.svelte'; let areMembersLimited: boolean; @@ -94,7 +94,7 @@ {#if isCloud && $organization?.billingPlan === BillingPlan.STARTER} FREE {/if} - {#if isCloud && $organization?.billingTrialStartDate && $daysLeftInTrial > 0 && $organization.billingPlan !== BillingPlan.STARTER} + {#if isCloud && $organization?.billingTrialStartDate && $daysLeftInTrial > 0 && $organization.billingPlan !== BillingPlan.STARTER && !TRIAL_PERIOD_OVERRIDE}
    Confirm your details - Confirm the details of your new organization and start your free trial. + Confirm the details of your new organization{TRIAL_PERIOD_OVERRIDE + ? '.' + : ' and start your free trial.'}

    Organization name

    @@ -123,9 +126,9 @@ {#if $createOrganization.billingPlan !== BillingPlan.STARTER}

    This amount, and any additional usage fees, will be charged on a recurring 30-day - billing cycle after your trial period ends on {toLocaleDate(billingPayDate.toString())}. + billing cycle{TRIAL_PERIOD_OVERRIDE + ? '.' + : ` after your trial period ends on ${toLocaleDate(billingPayDate.toString())}`}.

    {/if} diff --git a/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte b/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte index f6a3a8fa9..ef9231712 100644 --- a/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte +++ b/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte @@ -8,6 +8,7 @@ import { plansInfo, tierFree, tierPro, tierScale } from '$lib/stores/billing'; import { organizationList, type Organization } from '$lib/stores/organization'; import { updateStepStatus } from '$lib/stores/wizard'; + import { TRIAL_PERIOD_OVERRIDE } from '$lib/system'; import { createOrganization, createOrgSteps } from './store'; let showCustomId = false; @@ -108,7 +109,9 @@ {tierPro.description}

    - 14 DAY FREE TRIAL + {#if !TRIAL_PERIOD_OVERRIDE} + 14 DAY FREE TRIAL + {/if} @@ -131,7 +134,6 @@

    - COMING SOON
    diff --git a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte index b9378f5f1..ed4c76719 100644 --- a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte +++ b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte @@ -12,6 +12,7 @@ import { toLocaleDate } from '$lib/helpers/date'; import { showUsageRatesModal } from '$lib/stores/billing'; import { PaymentBoxes } from '$lib/components/billing'; + import { TRIAL_PERIOD_OVERRIDE } from '$lib/system'; const today = new Date(); const billingPayDate = new Date(today.getTime() + 44 * 24 * 60 * 60 * 1000); @@ -74,9 +75,9 @@ Payment details - Add a payment method to your organization. You will not be charged until your trial ends on {toLocaleDate(billingPayDate.toString())}. + Add a payment method to your organization. {#if !TRIAL_PERIOD_OVERRIDE}You will not be + charged until your trial ends on {toLocaleDate(billingPayDate.toString())}. + {/if} diff --git a/src/routes/console/wizard/cloudOrganization/store.ts b/src/routes/console/wizard/cloudOrganization/store.ts index 613259fe0..90749d5e3 100644 --- a/src/routes/console/wizard/cloudOrganization/store.ts +++ b/src/routes/console/wizard/cloudOrganization/store.ts @@ -1,10 +1,13 @@ import { BillingPlan } from '$lib/constants'; import type { WizardStepsType } from '$lib/layout/wizard.svelte'; import type { Tier } from '$lib/stores/billing'; +import { TRIAL_PERIOD_OVERRIDE } from '$lib/system'; import { writable } from 'svelte/store'; export const createOrgSteps = writable(new Map()); -export const createOrganizationFinalAction = writable('Start trial'); +export const createOrganizationFinalAction = writable( + TRIAL_PERIOD_OVERRIDE ? 'Create' : 'Start trial' +); export const createOrganization = writable<{ id?: string; diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte index 5a94e9ec8..da01e2449 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte @@ -13,6 +13,7 @@ import { Pill } from '$lib/elements'; import { BillingPlan } from '$lib/constants'; import { formatCurrency } from '$lib/helpers/numbers'; + import { TRIAL_PERIOD_OVERRIDE } from '$lib/system'; let usage: OrganizationUsage = null; let members: Models.MembershipList = null; @@ -161,7 +162,7 @@
    {#if $organization.billingPlan === BillingPlan.PRO} CURRENT PLAN - {:else} + {:else if !TRIAL_PERIOD_OVERRIDE} 14 DAY FREE TRIAL {/if}
    diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte index a67c5086e..604907f43 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte @@ -16,6 +16,7 @@ feedbackDowngradeOptions, isUpgrade } from './store'; + import { TRIAL_PERIOD_OVERRIDE } from '$lib/system'; const plan = $plansInfo.get($changeOrganizationTier.billingPlan); const collaboratorPrice = plan?.addons.member?.price ?? 0; @@ -77,7 +78,9 @@ Confirm your details - Confirm the details of your new organization and start your free trial. + Confirm the details of your new organization{TRIAL_PERIOD_OVERRIDE + ? '.' + : ' and start your free trial.'}

    Organization name

    @@ -144,9 +147,9 @@

    This amount, and any additional usage fees, will be charged on a recurring 30-day - billing cycle after your trial period ends on {toLocaleDate(billingPayDate.toString())}. + billing cycle{TRIAL_PERIOD_OVERRIDE + ? '.' + : ` after your trial period ends on ${toLocaleDate(billingPayDate.toString())}`}.

    diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts b/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts index 846dbabcc..f9cf2af84 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts @@ -1,11 +1,14 @@ import { BillingPlan } from '$lib/constants'; import type { WizardStepsType } from '$lib/layout/wizard.svelte'; import type { Tier } from '$lib/stores/billing'; +import { TRIAL_PERIOD_OVERRIDE } from '$lib/system'; import { writable } from 'svelte/store'; export const changeTierSteps = writable(new Map()); export const isUpgrade = writable(false); -export const changeOrganizationFinalAction = writable('Start trial'); +export const changeOrganizationFinalAction = writable( + TRIAL_PERIOD_OVERRIDE ? 'Create' : 'Start trial' +); export const changeOrganizationTier = writable<{ billingPlan: Tier; From 79a2853984031a1faff3173ea6d11f300d723953 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 2 Apr 2024 14:52:21 +0100 Subject: [PATCH 09/46] feat: new templates --- src/lib/stores/marketplace.ts | 732 ++++++++++++++++++++++++++++++++++ 1 file changed, 732 insertions(+) diff --git a/src/lib/stores/marketplace.ts b/src/lib/stores/marketplace.ts index 5e74be642..e7190d2a3 100644 --- a/src/lib/stores/marketplace.ts +++ b/src/lib/stores/marketplace.ts @@ -902,6 +902,738 @@ export const marketplace: MarketplaceTemplate[] = [ type: 'text' } ] + }, + { + icon: 'icon-chip', + id: 'text-generation-with-huggingface', + name: 'Text generation', + tagline: 'Generate text using the Hugging Face inference API.', + permissions: ['any'], + events: [], + cron: '', + timeout: 30, + usecases: ['AI'], + runtimes: [ + ...getRuntimes( + TemplateRuntimes.NODE, + 'npm install', + 'src/main.js', + 'node/text-generation-with-huggingface' + ) + ], + instructions: `For documentation and instructions check out file.`, + vcsProvider: 'github', + providerRepositoryId: 'templates', + providerOwner: 'appwrite', + providerBranch: 'main', + variables: [ + { + name: 'HUGGINGFACE_ACCESS_TOKEN', + description: `Secret for sending requests to the Hugging Face API. Learn more.`, + placeholder: 'hf_MUvn...', + required: true, + type: 'password' + } + ] + }, + { + icon: 'icon-chip', + id: 'language-translation-with-huggingface', + name: 'Language translation', + tagline: 'Translate text using the Hugging Face inference API.', + permissions: ['any'], + events: [], + cron: '', + timeout: 30, + usecases: ['AI'], + runtimes: [ + ...getRuntimes( + TemplateRuntimes.NODE, + 'npm install', + 'src/main.js', + 'node/language-translation-with-huggingface' + ) + ], + instructions: `For documentation and instructions check out file.`, + vcsProvider: 'github', + providerRepositoryId: 'templates', + providerOwner: 'appwrite', + providerBranch: 'main', + variables: [ + { + name: 'HUGGINGFACE_ACCESS_TOKEN', + description: `Secret for sending requests to the Hugging Face API. Learn more.`, + placeholder: 'hf_MUvn...', + required: true, + type: 'password' + } + ] + }, + { + icon: 'icon-chip', + id: 'image-classification-with-huggingface', + name: 'Image classification', + tagline: 'Classify images using the Hugging Face inference API.', + permissions: ['any'], + events: ['buckets.*.files.*.create'], + cron: '', + timeout: 15, + usecases: ['AI'], + runtimes: [ + ...getRuntimes( + TemplateRuntimes.NODE, + 'npm install && npm run setup', + 'src/main.js', + 'node/image-classification-with-huggingface' + ) + ], + instructions: `For documentation and instructions check out file.`, + vcsProvider: 'github', + providerRepositoryId: 'templates', + providerOwner: 'appwrite', + providerBranch: 'main', + variables: [ + { + name: 'APPWRITE_API_KEY', + description: `The API Key to authenticate against Appwrite's Server APIs. Learn more.`, + value: '', + placeholder: 'd1efb...aec35', + required: true, + type: 'password' + }, + { + name: 'APPWRITE_ENDPOINT', + description: `The URL endpoint of the Appwrite server. Learn more.`, + value: 'https://cloud.appwrite.io/v1', + placeholder: 'https://cloud.appwrite.io/v1', + required: false, + type: 'url' + }, + { + name: 'APPWRITE_DATABASE_ID', + description: `The ID of the database where the responses are stored. Learn more.`, + value: 'ai', + placeholder: 'ai', + required: false, + type: 'text' + }, + { + name: 'APPWRITE_COLLECTION_ID', + description: `The ID of the collection where the responses are stored. Learn more.`, + value: 'image_classification', + placeholder: 'image_classification', + required: false, + type: 'text' + }, + { + name: 'APPWRITE_BUCKET_ID', + description: `The ID of the bucket where the images are stored. Learn more.`, + value: 'image_classification', + placeholder: 'image_classification', + required: false, + type: 'text' + }, + { + name: 'HUGGINGFACE_ACCESS_TOKEN', + description: `Secret for sending requests to the Hugging Face API. Learn more.`, + placeholder: 'hf_MUvn...', + required: true, + type: 'password' + } + ] + }, + { + icon: 'icon-chip', + id: 'object-detection-with-huggingface', + name: 'Object detection', + tagline: 'Detect objects in images using the Hugging Face inference API.', + permissions: ['any'], + events: ['buckets.*.files.*.create'], + cron: '', + timeout: 15, + usecases: ['AI'], + runtimes: [ + ...getRuntimes( + TemplateRuntimes.NODE, + 'npm install && npm run setup', + 'src/main.js', + 'node/object-detection-with-huggingface' + ) + ], + instructions: `For documentation and instructions check out file.`, + vcsProvider: 'github', + providerRepositoryId: 'templates', + providerOwner: 'appwrite', + providerBranch: 'main', + variables: [ + { + name: 'APPWRITE_API_KEY', + description: `The API Key to authenticate against Appwrite's server APIs. Learn more.`, + value: '', + placeholder: 'd1efb...aec35', + required: true, + type: 'password' + }, + { + name: 'APPWRITE_ENDPOINT', + description: `The URL endpoint of the Appwrite server. Learn more.`, + value: 'https://cloud.appwrite.io/v1', + placeholder: 'https://cloud.appwrite.io/v1', + required: false, + type: 'url' + }, + { + name: 'APPWRITE_DATABASE_ID', + description: `The ID of the database where the responses are stored. Learn more.`, + value: 'ai', + placeholder: 'ai', + required: false, + type: 'text' + }, + { + name: 'APPWRITE_COLLECTION_ID', + description: `The ID of the collection where the responses are stored. Learn more.`, + value: 'object_detection', + placeholder: 'object_detection', + required: false, + type: 'text' + }, + { + name: 'APPWRITE_BUCKET_ID', + description: `The ID of the bucket where the images are stored. Learn more.`, + value: 'object_detection', + placeholder: 'object_detection', + required: false, + type: 'text' + }, + { + name: 'HUGGINGFACE_ACCESS_TOKEN', + description: `Secret for sending requests to the Hugging Face API. Learn more.`, + placeholder: 'hf_MUvn...', + required: true, + type: 'password' + } + ] + }, + { + icon: 'icon-chip', + id: 'speech-recognition-with-huggingface', + name: 'Speech recognition', + tagline: 'Transcribe audio to text using the Hugging Face inference API.', + permissions: ['any'], + events: ['buckets.*.files.*.create'], + cron: '', + timeout: 15, + usecases: ['AI'], + runtimes: [ + ...getRuntimes( + TemplateRuntimes.NODE, + 'npm install && npm run setup', + 'src/main.js', + 'node/speech-recognition-with-huggingface' + ) + ], + instructions: `For documentation and instructions check out file.`, + vcsProvider: 'github', + providerRepositoryId: 'templates', + providerOwner: 'appwrite', + providerBranch: 'main', + variables: [ + { + name: 'APPWRITE_API_KEY', + description: `The API Key to authenticate against Appwrite's server APIs. Learn more.`, + value: '', + placeholder: 'd1efb...aec35', + required: true, + type: 'password' + }, + { + name: 'APPWRITE_ENDPOINT', + description: `The URL endpoint of the Appwrite server. Learn more.`, + value: 'https://cloud.appwrite.io/v1', + placeholder: 'https://cloud.appwrite.io/v1', + required: false, + type: 'url' + }, + { + name: 'APPWRITE_DATABASE_ID', + description: `The ID of the database where the responses are stored. Learn more.`, + value: 'ai', + placeholder: 'ai', + required: false, + type: 'text' + }, + { + name: 'APPWRITE_COLLECTION_ID', + description: `The ID of the collection where the responses are stored. Learn more.`, + value: 'speech_recognition', + placeholder: 'speech_recognition', + required: false, + type: 'text' + }, + { + name: 'APPWRITE_BUCKET_ID', + description: `The ID of the bucket where audio is stored. Learn more.`, + value: 'speech_recognition', + placeholder: 'speech_recognition', + required: false, + type: 'text' + }, + { + name: 'HUGGINGFACE_ACCESS_TOKEN', + description: `Secret for sending requests to the Hugging Face API. Learn more.`, + placeholder: 'hf_MUvn...', + required: true, + type: 'password' + } + ] + }, + { + icon: 'icon-chip', + id: 'text-to-speech-with-huggingface', + name: 'Text to speech', + tagline: 'Convert text to speech using the Hugging Face inference API.', + permissions: ['any'], + events: ['databases.*.collections.*.documents.*.create'], + cron: '', + timeout: 15, + usecases: ['AI'], + runtimes: [ + ...getRuntimes( + TemplateRuntimes.NODE, + 'npm install && npm run setup', + 'src/main.js', + 'node/text-to-speech-with-huggingface' + ) + ], + instructions: `For documentation and instructions check out file.`, + vcsProvider: 'github', + providerRepositoryId: 'templates', + providerOwner: 'appwrite', + providerBranch: 'main', + variables: [ + { + name: 'APPWRITE_API_KEY', + description: `The API Key to authenticate against Appwrite's server APIs. Learn more.`, + value: '', + placeholder: 'd1efb...aec35', + required: true, + type: 'password' + }, + { + name: 'APPWRITE_ENDPOINT', + description: `The URL endpoint of the Appwrite server. Learn more.`, + value: 'https://cloud.appwrite.io/v1', + placeholder: 'https://cloud.appwrite.io/v1', + required: false, + type: 'url' + }, + { + name: 'APPWRITE_DATABASE_ID', + description: `The ID of the database where the responses are stored. Learn more.`, + value: 'ai', + placeholder: 'ai', + required: false, + type: 'text' + }, + { + name: 'APPWRITE_COLLECTION_ID', + description: `The ID of the collection where the responses are stored. Learn more.`, + value: 'speech_recognition', + placeholder: 'speech_recognition', + required: false, + type: 'text' + }, + { + name: 'APPWRITE_BUCKET_ID', + description: `The ID of the bucket where audio is stored. Learn more.`, + value: 'speech_recognition', + placeholder: 'speech_recognition', + required: false, + type: 'text' + }, + { + name: 'HUGGINGFACE_ACCESS_TOKEN', + description: `Secret for sending requests to the Hugging Face API. Learn more.`, + placeholder: 'hf_MUvn...', + required: true, + type: 'password' + } + ] + }, + { + icon: 'icon-chip', + id: 'chat-with-perplexity-ai', + name: 'Chat with Perplexity AI', + tagline: 'Create a chatbot using the Perplexity AI API.', + permissions: ['any'], + events: [], + cron: '', + timeout: 15, + usecases: ['AI'], + runtimes: [ + ...getRuntimes( + TemplateRuntimes.NODE, + 'npm install', + 'src/main.js', + 'node/chat-with-perplexity-ai' + ) + ], + instructions: `For documentation and instructions check out file.`, + vcsProvider: 'github', + providerRepositoryId: 'templates', + providerOwner: 'appwrite', + providerBranch: 'main', + variables: [ + { + name: 'PERPLEXITY_API_KEY', + description: `A unique key used to authenticate with the Perplexity API. Learn more.`, + placeholder: `pplex-68...999`, + required: true, + type: 'password' + }, + { + name: 'PERPLEXITY_MAX_TOKENS', + description: `The maximum number of tokens to generate. Learn more.`, + placeholder: `512`, + required: false, + type: 'number' + } + ] + }, + { + icon: 'icon-chip', + id: 'generate-with-replicate', + name: 'Generate with Replicate', + tagline: "Generate text, audio and images using Replicate's API.", + permissions: ['any'], + events: [], + cron: '', + timeout: 300, + usecases: ['AI'], + runtimes: [ + ...getRuntimes( + TemplateRuntimes.NODE, + 'npm install', + 'src/main.js', + 'node/generate-with-replicate' + ) + ], + instructions: `For documentation and instructions check out file.`, + vcsProvider: 'github', + providerRepositoryId: 'templates', + providerOwner: 'appwrite', + providerBranch: 'main', + variables: [ + { + name: 'REPLICATE_API_KEY', + description: `A unique key used to authenticate with the Replicate API. Learn more.`, + value: '', + placeholder: 'd1efb...aec35', + required: true, + type: 'password' + } + ] + }, + { + icon: 'icon-chip', + id: 'chat-with-perplexity-ai', + name: 'Chat with Perplexity AI', + tagline: 'Create a chatbot using the Perplexity AI API.', + permissions: ['any'], + events: [], + cron: '', + timeout: 15, + usecases: ['AI'], + runtimes: [ + ...getRuntimes( + TemplateRuntimes.NODE, + 'npm install', + 'src/main.js', + 'node/chat-with-perplexity-ai' + ) + ], + instructions: `For documentation and instructions check out file.`, + vcsProvider: 'github', + providerRepositoryId: 'templates', + providerOwner: 'appwrite', + providerBranch: 'main', + variables: [ + { + name: 'PERPLEXITY_API_KEY', + description: `A unique key used to authenticate with the Perplexity API. Learn more.`, + placeholder: `pplex-68...999`, + required: true, + type: 'password' + }, + { + name: 'PERPLEXITY_MAX_TOKENS', + description: `The maximum number of tokens to generate. Learn more.`, + placeholder: `512`, + required: false, + type: 'number' + } + ] + }, + { + icon: 'icon-chip', + id: 'generate-with-replicate', + name: 'Generate with Replicate', + tagline: "Generate text, audio and images using Replicate's API.", + permissions: ['any'], + events: [], + cron: '', + timeout: 300, + usecases: ['AI'], + runtimes: [ + ...getRuntimes( + TemplateRuntimes.NODE, + 'npm install', + 'src/main.js', + 'node/generate-with-replicate' + ) + ], + instructions: `For documentation and instructions check out file.`, + vcsProvider: 'github', + providerRepositoryId: 'templates', + providerOwner: 'appwrite', + providerBranch: 'main', + variables: [ + { + name: 'REPLICATE_API_KEY', + description: `A unique key used to authenticate with the Replicate API. Learn more.`, + value: '', + placeholder: 'd1efb...aec35', + required: true, + type: 'password' + } + ] + }, + { + icon: 'icon-chip', + id: 'sync-with-pinecone', + name: 'Sync with Pinecone', + tagline: "Sync your Appwrite database with Pinecone's vector database.", + permissions: ['any'], + events: [], + cron: '', + timeout: 30, + usecases: ['AI'], + runtimes: [ + ...getRuntimes( + TemplateRuntimes.NODE, + 'npm install', + 'src/main.js', + 'node/sync-with-pinecone' + ) + ], + instructions: `For documentation and instructions check out file.`, + vcsProvider: 'github', + providerRepositoryId: 'templates', + providerOwner: 'appwrite', + providerBranch: 'main', + variables: [ + { + name: 'OPENAI_API_KEY', + description: `A unique key used to authenticate with the OpenAI API. This is a paid service and you will be charged for each request made to the API. Learn more.`, + value: '', + placeholder: 'sk-wzG...vcy', + required: true, + type: 'password' + }, + { + name: 'PINECONE_API_KEY', + description: `A unique key used to authenticate with the Pinecone API. Learn more.`, + placeholder: 'd1efb...aec35', + required: true, + type: 'password' + }, + { + name: 'PINECONE_INDEX_NAME', + description: `The name of the index in Pinecone. Learn more.`, + placeholder: 'my-index', + required: true, + type: 'text' + }, + { + name: 'APPWRITE_API_KEY', + description: `The API Key to authenticate against Appwrite's server APIs. Learn more.`, + value: '', + placeholder: 'd1efb...aec35', + required: true, + type: 'password' + }, + { + name: 'APPWRITE_ENDPOINT', + description: `The URL endpoint of the Appwrite server. Learn more.`, + value: 'https://cloud.appwrite.io/v1', + placeholder: 'https://cloud.appwrite.io/v1', + required: false, + type: 'url' + }, + { + name: 'APPWRITE_DATABASE_ID', + description: `The ID of the database where the documents are stored. Learn more.`, + placeholder: 'my-database', + required: true, + type: 'text' + }, + { + name: 'APPWRITE_COLLECTION_ID', + description: `The ID of the collection where the documents are stored. Learn more.`, + placeholder: 'my-collection', + required: true, + type: 'text' + } + ] + }, + { + icon: 'icon-chip', + id: 'rag-with-langchain', + name: 'RAG with LangChain', + tagline: 'Generate text using a LangChain RAG model', + permissions: ['any'], + events: [], + cron: '', + timeout: 30, + usecases: ['AI'], + runtimes: [ + ...getRuntimes( + TemplateRuntimes.NODE, + 'npm install', + 'src/main.js', + 'node/rag-with-langchain' + ) + ], + instructions: `For documentation and instructions check out file.`, + vcsProvider: 'github', + providerRepositoryId: 'templates', + providerOwner: 'appwrite', + providerBranch: 'main', + variables: [ + { + name: 'OPENAI_API_KEY', + description: `A unique key used to authenticate with the OpenAI API. This is a paid service and you will be charged for each request made to the API. Learn more.`, + value: '', + placeholder: 'sk-wzG...vcy', + required: true, + type: 'password' + }, + { + name: 'PINECONE_API_KEY', + description: `A unique key used to authenticate with the Pinecone API. Learn more.`, + placeholder: 'd1efb...aec35', + required: true, + type: 'password' + }, + { + name: 'PINECONE_INDEX_NAME', + description: `The name of the index in Pinecone. Learn more.`, + placeholder: 'my-index', + required: true, + type: 'text' + }, + { + name: 'APPWRITE_API_KEY', + description: `The API Key to authenticate against Appwrite's server APIs. Learn more.`, + value: '', + placeholder: 'd1efb...aec35', + required: true, + type: 'password' + }, + { + name: 'APPWRITE_ENDPOINT', + description: `The URL endpoint of the Appwrite server. Learn more.`, + value: 'https://cloud.appwrite.io/v1', + placeholder: 'https://cloud.appwrite.io/v1', + required: false, + type: 'url' + }, + { + name: 'APPWRITE_DATABASE_ID', + description: `The ID of the database where the documents are stored. Learn more.`, + placeholder: 'my-database', + required: true, + type: 'text' + }, + { + name: 'APPWRITE_COLLECTION_ID', + description: `The ID of the collection where the documents are stored. Learn more.`, + placeholder: 'my-collection', + required: true, + type: 'text' + } + ] + }, + { + icon: 'icon-chip', + id: 'speak-with-elevenlabs', + name: 'Speak with ElevenLabs', + tagline: 'Convert text to speech using the ElevenLabs API.', + permissions: ['any'], + cron: '', + events: [], + timeout: 15, + usecases: ['AI'], + runtimes: [ + ...getRuntimes( + TemplateRuntimes.NODE, + 'npm install', + 'src/main.js', + 'node/speak-with-elevenlabs' + ) + ], + instructions: `For documentation and instructions check out file.`, + vcsProvider: 'github', + providerRepositoryId: 'templates', + providerOwner: 'appwrite', + providerBranch: 'main', + variables: [ + { + name: 'ELEVENLABS_API_KEY', + description: `A unique key used to authenticate with the ElevenLabs API. Learn more.`, + placeholder: 'd03xxxxxxxx26', + required: true, + type: 'password' + }, + { + name: 'APPWRITE_API_KEY', + description: `The API Key to authenticate against Appwrite's server APIs. Learn more.`, + value: '', + placeholder: 'd1efb...aec35', + required: true, + type: 'password' + }, + { + name: 'APPWRITE_ENDPOINT', + description: `The URL endpoint of the Appwrite server. Learn more.`, + value: 'https://cloud.appwrite.io/v1', + placeholder: 'https://cloud.appwrite.io/v1', + required: false, + type: 'url' + }, + { + name: 'APPWRITE_DATABASE_ID', + description: `The ID of the database where the responses are stored. Learn more.`, + placeholder: 'my-database', + required: true, + type: 'text' + }, + { + name: 'APPWRITE_COLLECTION_ID', + description: `The ID of the collection where the responses are stored. Learn more.`, + placeholder: 'my-collection', + required: true, + type: 'text' + }, + { + name: 'APPWRITE_BUCKET_ID', + description: `The ID of the bucket where audio is stored. Learn more.`, + placeholder: 'generated_speech', + required: true, + type: 'text' + } + ] } ]; From ec6a93cdc3e709d0a4612e5a437b7b5e7c4c9891 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 2 Apr 2024 15:27:11 +0100 Subject: [PATCH 10/46] chore: remove duplicate perplexity --- src/lib/stores/marketplace.ts | 40 ----------------------------------- 1 file changed, 40 deletions(-) diff --git a/src/lib/stores/marketplace.ts b/src/lib/stores/marketplace.ts index e7190d2a3..02484e498 100644 --- a/src/lib/stores/marketplace.ts +++ b/src/lib/stores/marketplace.ts @@ -1261,46 +1261,6 @@ export const marketplace: MarketplaceTemplate[] = [ } ] }, - { - icon: 'icon-chip', - id: 'chat-with-perplexity-ai', - name: 'Chat with Perplexity AI', - tagline: 'Create a chatbot using the Perplexity AI API.', - permissions: ['any'], - events: [], - cron: '', - timeout: 15, - usecases: ['AI'], - runtimes: [ - ...getRuntimes( - TemplateRuntimes.NODE, - 'npm install', - 'src/main.js', - 'node/chat-with-perplexity-ai' - ) - ], - instructions: `For documentation and instructions check out file.`, - vcsProvider: 'github', - providerRepositoryId: 'templates', - providerOwner: 'appwrite', - providerBranch: 'main', - variables: [ - { - name: 'PERPLEXITY_API_KEY', - description: `A unique key used to authenticate with the Perplexity API. Learn more.`, - placeholder: `pplex-68...999`, - required: true, - type: 'password' - }, - { - name: 'PERPLEXITY_MAX_TOKENS', - description: `The maximum number of tokens to generate. Learn more.`, - placeholder: `512`, - required: false, - type: 'number' - } - ] - }, { icon: 'icon-chip', id: 'generate-with-replicate', From 95dc555ee3a02577056c39c701b2fdf08a107043 Mon Sep 17 00:00:00 2001 From: Arman Date: Tue, 2 Apr 2024 17:23:12 +0200 Subject: [PATCH 11/46] fix: race condition during invalidation --- .../function-[function]/settings/+page.svelte | 11 +++++------ .../console/project-[project]/updateVariables.svelte | 8 +++++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte b/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte index 4dac5f427..2384dc1bd 100644 --- a/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte +++ b/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte @@ -24,21 +24,20 @@ const sdkCreateVariable = async (key: string, value: string) => { await sdk.forProject.functions.createVariable($func.$id, key, value); - await invalidate(Dependencies.VARIABLES); - await invalidate(Dependencies.FUNCTION); + await Promise.all([invalidate(Dependencies.VARIABLES), invalidate(Dependencies.FUNCTION)]); }; const sdkUpdateVariable = async (variableId: string, key: string, value: string) => { await sdk.forProject.functions.updateVariable($func.$id, variableId, key, value); - await invalidate(Dependencies.VARIABLES); - await invalidate(Dependencies.FUNCTION); + await Promise.all([invalidate(Dependencies.VARIABLES), invalidate(Dependencies.FUNCTION)]); }; const sdkDeleteVariable = async (variableId: string) => { await sdk.forProject.functions.deleteVariable($func.$id, variableId); - await invalidate(Dependencies.VARIABLES); - await invalidate(Dependencies.FUNCTION); + await Promise.all([invalidate(Dependencies.VARIABLES), invalidate(Dependencies.FUNCTION)]); }; + + $: console.log(data.variables); diff --git a/src/routes/console/project-[project]/updateVariables.svelte b/src/routes/console/project-[project]/updateVariables.svelte index 8a17fa61d..892ed7ef4 100644 --- a/src/routes/console/project-[project]/updateVariables.svelte +++ b/src/routes/console/project-[project]/updateVariables.svelte @@ -138,9 +138,11 @@ selectedVar = null; showPromoteModal = false; - await invalidate(Dependencies.FUNCTION); - await invalidate(Dependencies.VARIABLES); - await invalidate(Dependencies.PROJECT_VARIABLES); + await Promise.all([ + await invalidate(Dependencies.FUNCTION), + await invalidate(Dependencies.VARIABLES), + await invalidate(Dependencies.PROJECT_VARIABLES) + ]); addNotification({ type: 'success', From 230a7621b446d9f5976b383b722b781a4deabb00 Mon Sep 17 00:00:00 2001 From: Arman Date: Tue, 2 Apr 2024 17:23:49 +0200 Subject: [PATCH 12/46] remove console log --- .../functions/function-[function]/settings/+page.svelte | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte b/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte index 2384dc1bd..db5149a6a 100644 --- a/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte +++ b/src/routes/console/project-[project]/functions/function-[function]/settings/+page.svelte @@ -36,8 +36,6 @@ await sdk.forProject.functions.deleteVariable($func.$id, variableId); await Promise.all([invalidate(Dependencies.VARIABLES), invalidate(Dependencies.FUNCTION)]); }; - - $: console.log(data.variables); From b79e0347a5dcaffa1393b0bb39ba60ad3d6a879d Mon Sep 17 00:00:00 2001 From: Arman Date: Tue, 2 Apr 2024 17:30:40 +0200 Subject: [PATCH 13/46] fix: upload wizard not closing --- .../storage/bucket-[bucket]/create-file/create.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte index 99c989561..aeed538c9 100644 --- a/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte @@ -29,7 +29,7 @@ async function create() { try { - await uploader.uploadFile( + uploader.uploadFile( bucketId, $createFile.id ?? ID.unique(), $createFile.files[0], From b3b42ee512fd89c7b5240eae1ea8f130737a564c Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 3 Apr 2024 14:03:13 +0200 Subject: [PATCH 14/46] feat: add downgrade alerts --- .../confirmDetails.svelte | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte index a67c5086e..b89bc897c 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte @@ -1,5 +1,5 @@ {#if $organization} @@ -54,7 +56,7 @@
    {tierToPlan($organization?.billingPlan)?.name} plan
    - {#if $organization?.billingPlan !== BillingPlan.STARTER && isTrial && } + {#if $organization?.billingPlan !== BillingPlan.STARTER && isTrial && !TRIAL_PERIOD_OVERRIDE} TRIAL {/if} From 806c71bcc00142688405a474a95a8364199cc649 Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 3 Apr 2024 14:12:36 +0200 Subject: [PATCH 16/46] copy fix --- .../console/organization-[organization]/billing/+page.svelte | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/routes/console/organization-[organization]/billing/+page.svelte b/src/routes/console/organization-[organization]/billing/+page.svelte index 379814dd1..6095081f8 100644 --- a/src/routes/console/organization-[organization]/billing/+page.svelte +++ b/src/routes/console/organization-[organization]/billing/+page.svelte @@ -95,9 +95,8 @@ {/if} {#if $organization?.billingPlanDowngrade} - Your organization will change to a Starter plan once your current billing cycle ends on {toLocaleDate( - $organization.billingNextInvoiceDate - )}. + Your organization will change to a Starter plan once your current billing cycle ends and + your invoice is paid on {toLocaleDate($organization.billingNextInvoiceDate)}. {/if}
    From dae1177ba00942efb034ad4f73eb63dd2dd41e49 Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 3 Apr 2024 14:14:55 +0200 Subject: [PATCH 17/46] fix: date --- .../wizard/cloudOrganizationChangeTier/confirmDetails.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte index b89bc897c..8c1a3e3da 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte @@ -62,11 +62,11 @@ Your {tierToPlan($organization.billingPlan).name} plan subscription will end on {toLocaleDate( - $organization.billingCurrentInvoiceDate + $organization.billingNextInvoiceDate )}

    Following the payment of your final invoice on {toLocaleDate( - $organization.billingCurrentInvoiceDate + $organization.billingNextInvoiceDate )}, your organization will switch to the {tierToPlan( $changeOrganizationTier.billingPlan ).name} plan. Until then, you can continue to use the resources available to the {tierToPlan( From e2dd89338fa09bc150bbad867d7197a6b35d334c Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:31:43 +0100 Subject: [PATCH 18/46] feat: hide python-ml --- src/routes/console/project-[project]/functions/store.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/routes/console/project-[project]/functions/store.ts b/src/routes/console/project-[project]/functions/store.ts index 3acf62136..4a52582a7 100644 --- a/src/routes/console/project-[project]/functions/store.ts +++ b/src/routes/console/project-[project]/functions/store.ts @@ -2,10 +2,11 @@ import { page } from '$app/stores'; import { derived } from 'svelte/store'; import type { Models } from '@appwrite.io/console'; -export const runtimesList = derived( - page, - async ($page) => (await $page.data.runtimesList) as Models.RuntimeList -); +export const runtimesList = derived(page, async ($page) => { + const { runtimes } = (await $page.data.runtimes) as Models.RuntimeList; + const filtered = runtimes.filter((runtime) => !runtime.name.startsWith('python-ml')); + return { runtimes: filtered, total: filtered.length }; +}); export const baseRuntimesList = derived(runtimesList, async ($runtimesList) => { const baseRuntimes = new Map(); From 04ac6cc5cf97dd2561dce33036abd5e349cca504 Mon Sep 17 00:00:00 2001 From: Arman Date: Fri, 5 Apr 2024 16:56:05 +0200 Subject: [PATCH 19/46] feat: add `limitReached` banner and delete previous modal --- .../billing/alerts/limitReached.svelte | 43 +++++++ src/lib/layout/header.svelte | 14 --- src/lib/stores/billing.ts | 24 +++- src/routes/console/+layout.svelte | 6 +- .../excesLimitModal.svelte | 106 ------------------ .../organization-[organization]/store.ts | 3 +- .../usage/[[invoice]]/+page.svelte | 3 +- .../settings/usage/[[invoice]]/+page.svelte | 5 +- 8 files changed, 74 insertions(+), 130 deletions(-) create mode 100644 src/lib/components/billing/alerts/limitReached.svelte delete mode 100644 src/routes/console/organization-[organization]/excesLimitModal.svelte diff --git a/src/lib/components/billing/alerts/limitReached.svelte b/src/lib/components/billing/alerts/limitReached.svelte new file mode 100644 index 000000000..9844136b6 --- /dev/null +++ b/src/lib/components/billing/alerts/limitReached.svelte @@ -0,0 +1,43 @@ + + +{#if $organization?.$id && $organization?.billingPlan === BillingPlan.STARTER && $readOnly && !$page.url.pathname.includes('/console/account')} + + + Usage for the {$organization.name} organization has reached the limits of the Starter + plan. Consider upgrading to increase your resource usage. + + + + + + +{/if} diff --git a/src/lib/layout/header.svelte b/src/lib/layout/header.svelte index 9dbc534c5..16c97001a 100644 --- a/src/lib/layout/header.svelte +++ b/src/lib/layout/header.svelte @@ -24,9 +24,6 @@ import CreateOrganizationCloud from '$routes/console/createOrganizationCloud.svelte'; import { Feedback } from '$lib/components/feedback'; import ChangeOrganizationTierCloud from '$routes/console/changeOrganizationTierCloud.svelte'; - import { Pill } from '$lib/elements'; - import { showExcess } from '$routes/console/organization-[organization]/store'; - import { readOnly } from '$lib/stores/billing'; import { BillingPlan } from '$lib/constants'; let showDropdown = false; @@ -105,17 +102,6 @@ {/if} -{#if !$page.url.pathname.includes('/console/account') && $readOnly} -

    - ($showExcess = true)}> -
    -
    -
    -
    -{/if} -
    Bandwidth -

    Calculated for all bandwidth used in your project.

    +

    + Calculated for all bandwidth used across your project. Resets at the start of each + billing cycle. +

    {#if network} {@const humanized = humanFileSize(total(network))} From ada46586e8a547ba117b82e6acf82cf7b2e24d1e Mon Sep 17 00:00:00 2001 From: Arman Date: Fri, 5 Apr 2024 17:15:17 +0200 Subject: [PATCH 20/46] feat: add notificaiton for when a service is over the 75% mark --- src/lib/stores/billing.ts | 62 +++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index 8155f4a4a..50f03d7a4 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -24,6 +24,10 @@ import { BillingPlan } from '$lib/constants'; import PaymentMandate from '$lib/components/billing/alerts/paymentMandate.svelte'; import MissingPaymentMethod from '$lib/components/billing/alerts/missingPaymentMethod.svelte'; import LimitReached from '$lib/components/billing/alerts/limitReached.svelte'; +import { wizard } from './wizard'; +import ChangeOrganizationTierCloud from '$routes/console/changeOrganizationTierCloud.svelte'; +import { trackEvent } from '$lib/actions/analytics'; +import { browser } from '$app/environment'; export type Tier = 'tier-0' | 'tier-1' | 'tier-2'; @@ -189,19 +193,20 @@ export async function checkForUsageLimit(org: Organization) { return; } const { bandwidth, documents, executions, storage, users } = org?.billingLimits ?? {}; + const resources = [ + { value: bandwidth, name: 'bandwidth' }, + { value: documents, name: 'documents' }, + { value: executions, name: 'executions' }, + { value: storage, name: 'storage' }, + { value: users, name: 'users' } + ]; + const members = await sdk.forConsole.teams.listMemberships(org.$id); const plan = get(plansInfo)?.get(org.billingPlan); const membersOverflow = members?.total > plan.members ? members.total - (plan.members || members.total) : 0; - if ( - bandwidth >= 100 || - documents >= 100 || - executions >= 100 || - storage >= 100 || - users >= 100 || - membersOverflow > 0 - ) { + if (resources.some((r) => r.value >= 100) || membersOverflow > 0) { readOnly.set(true); headerAlert.add({ id: 'limitReached', @@ -209,15 +214,40 @@ export async function checkForUsageLimit(org: Organization) { show: true, importance: 7 }); - } else if ( - bandwidth >= 75 || - documents >= 75 || - executions >= 75 || - storage >= 75 || - users >= 75 - ) { + } else if (resources.some((r) => r.value >= 75)) { readOnly.set(false); - //show notification + if (browser) { + const lastNotification = + parseInt(localStorage.getItem('limitReachedNotification')) ?? 0; + const now = new Date().getTime(); + if (now - lastNotification < 1000 * 60 * 60 * 24 * 3) return; + + localStorage.setItem('limitReachedNotification', now.toString()); + addNotification({ + type: 'warning', + isHtml: true, + timeout: 0, + message: `${org.name} has reached 75% of the Starter plan's ${resources.find((r) => r.value >= 75).name} limit. Upgrade to ensure there are no service disruptions.`, + buttons: [ + { + name: 'View usage', + method: () => { + goto(`${base}/console/organization-${org.$id}/usage`); + } + }, + { + name: 'Upgrade plan', + method: () => { + wizard.start(ChangeOrganizationTierCloud); + trackEvent('click_organization_upgrade', { + from: 'button', + source: 'limit_reached_notification' + }); + } + } + ] + }); + } } else { readOnly.set(false); } From 9210a73b412e4e9f4fb6282da87f1355c4b5b468 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 5 Apr 2024 18:22:00 +0100 Subject: [PATCH 21/46] fix: runtimes list --- src/routes/console/project-[project]/functions/store.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/functions/store.ts b/src/routes/console/project-[project]/functions/store.ts index 4a52582a7..8e8c7db77 100644 --- a/src/routes/console/project-[project]/functions/store.ts +++ b/src/routes/console/project-[project]/functions/store.ts @@ -3,7 +3,7 @@ import { derived } from 'svelte/store'; import type { Models } from '@appwrite.io/console'; export const runtimesList = derived(page, async ($page) => { - const { runtimes } = (await $page.data.runtimes) as Models.RuntimeList; + const { runtimes } = (await $page.data.runtimesList) as Models.RuntimeList; const filtered = runtimes.filter((runtime) => !runtime.name.startsWith('python-ml')); return { runtimes: filtered, total: filtered.length }; }); From 4d5950a6372d7cbf0c25f178a915ae45444692f7 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 5 Apr 2024 19:05:55 +0100 Subject: [PATCH 22/46] fix: runtimes list --- src/routes/console/project-[project]/functions/store.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/functions/store.ts b/src/routes/console/project-[project]/functions/store.ts index 8e8c7db77..172a5ce42 100644 --- a/src/routes/console/project-[project]/functions/store.ts +++ b/src/routes/console/project-[project]/functions/store.ts @@ -4,7 +4,7 @@ import type { Models } from '@appwrite.io/console'; export const runtimesList = derived(page, async ($page) => { const { runtimes } = (await $page.data.runtimesList) as Models.RuntimeList; - const filtered = runtimes.filter((runtime) => !runtime.name.startsWith('python-ml')); + const filtered = runtimes.filter((runtime) => !runtime.$id.startsWith('python-ml')); return { runtimes: filtered, total: filtered.length }; }); From 330a447196011ec3841b7431807bcc135265d505 Mon Sep 17 00:00:00 2001 From: Arman Date: Mon, 8 Apr 2024 13:26:41 +0200 Subject: [PATCH 23/46] feat: show notification once a day --- src/lib/stores/billing.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index 50f03d7a4..362dcdf6e 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -220,7 +220,7 @@ export async function checkForUsageLimit(org: Organization) { const lastNotification = parseInt(localStorage.getItem('limitReachedNotification')) ?? 0; const now = new Date().getTime(); - if (now - lastNotification < 1000 * 60 * 60 * 24 * 3) return; + if (now - lastNotification < 1000 * 60 * 60 * 24) return; localStorage.setItem('limitReachedNotification', now.toString()); addNotification({ From 6e09e6cc756de7d58e984b2692737c26e062bfa8 Mon Sep 17 00:00:00 2001 From: Arman Date: Mon, 8 Apr 2024 13:32:18 +0200 Subject: [PATCH 24/46] feat: update message --- src/lib/stores/billing.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index 362dcdf6e..be97eab8a 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -223,11 +223,15 @@ export async function checkForUsageLimit(org: Organization) { if (now - lastNotification < 1000 * 60 * 60 * 24) return; localStorage.setItem('limitReachedNotification', now.toString()); + let message = `${org.name} has reached 75% of the Starter 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 ${org.name} has reached 75% of the Starter plan limit. Upgrade to ensure there are no service disruptions.`; + } addNotification({ type: 'warning', isHtml: true, timeout: 0, - message: `${org.name} has reached 75% of the Starter plan's ${resources.find((r) => r.value >= 75).name} limit. Upgrade to ensure there are no service disruptions.`, + message, buttons: [ { name: 'View usage', From 3da6609257e0afd197bd94705b21c3662b6aece7 Mon Sep 17 00:00:00 2001 From: Arman Date: Mon, 8 Apr 2024 15:08:14 +0200 Subject: [PATCH 25/46] chore: remove old upload modal --- .../storage/bucket-[bucket]/create.svelte | 105 ------------------ 1 file changed, 105 deletions(-) delete mode 100644 src/routes/console/project-[project]/storage/bucket-[bucket]/create.svelte diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/create.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/create.svelte deleted file mode 100644 index 209f1ded2..000000000 --- a/src/routes/console/project-[project]/storage/bucket-[bucket]/create.svelte +++ /dev/null @@ -1,105 +0,0 @@ - - - - -
    - -
    - - {#if !showCustomId} -
    - (showCustomId = !showCustomId)}> - -
    - {:else} - - {/if} - Permissions -

    - Choose who can access your buckets and files. For more information, visit our - - Permissions guide - . -

    - {#if $bucket.fileSecurity} -
    - - File security enabled - Users will be able to access this file if they have been granted - either File or Bucket permissions. - -
    -
    - -
    - {:else} - - File security disabled - If you want to assign file permissions, navigate to Bucket settings and enable file security. - Otherwise, only Bucket permissions will be used. - - {/if} -
    - - - - -
    From 1de5e3bc98946c2ad48d97ab08d31f821f4c0f99 Mon Sep 17 00:00:00 2001 From: Arman Date: Mon, 8 Apr 2024 15:08:29 +0200 Subject: [PATCH 26/46] chore: success notification copy --- .../storage/bucket-[bucket]/create-file/create.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte index aeed538c9..66315f0dd 100644 --- a/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte +++ b/src/routes/console/project-[project]/storage/bucket-[bucket]/create-file/create.svelte @@ -42,7 +42,7 @@ addNotification({ type: 'success', - message: `File has been uploaded` + message: `File upload in progress` }); trackEvent(Submit.FileCreate, { customId: !!$createFile.id From 5ec52553a22e632fd06e1d30d611bf5d7686029a Mon Sep 17 00:00:00 2001 From: Arman Date: Tue, 9 Apr 2024 09:46:44 +0200 Subject: [PATCH 27/46] fix: replace card flow --- .../billing/replaceCard.svelte | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/routes/console/organization-[organization]/billing/replaceCard.svelte b/src/routes/console/organization-[organization]/billing/replaceCard.svelte index 639964119..92e1bd949 100644 --- a/src/routes/console/organization-[organization]/billing/replaceCard.svelte +++ b/src/routes/console/organization-[organization]/billing/replaceCard.svelte @@ -5,7 +5,7 @@ import { sdk } from '$lib/stores/sdk'; import { organization } from '$lib/stores/organization'; import { Dependencies } from '$lib/constants'; - import { submitStripeCard } from '$lib/stores/stripe'; + import { initializeStripe, isStripeInitialized, submitStripeCard } from '$lib/stores/stripe'; import { onMount } from 'svelte'; import type { PaymentList } from '$lib/sdk/billing'; import { addNotification } from '$lib/stores/notifications'; @@ -21,13 +21,19 @@ onMount(async () => { methods = await sdk.forConsole.billing.listPaymentMethods(); - - if (!$organization.paymentMethodId && !$organization.backupPaymentMethodId) { - selectedPaymentMethodId = methods?.total ? methods.paymentMethods[0].$id : null; - } selectedPaymentMethodId = isBackup ? $organization.backupPaymentMethodId : $organization.paymentMethodId; + if (!$organization.paymentMethodId && !$organization.backupPaymentMethodId) { + selectedPaymentMethodId = methods?.total ? methods.paymentMethods[0].$id : null; + } + // If the selected payment method does not belong to the current user, reset it + if ( + methods?.total && + !methods.paymentMethods.some((method) => method.$id === selectedPaymentMethodId) + ) { + selectedPaymentMethodId = null; + } }); async function handleSubmit() { @@ -82,6 +88,14 @@ $: filteredMethods = methods?.paymentMethods.filter((method) => !!method?.last4); + $: if (selectedPaymentMethodId === null && !$isStripeInitialized) { + initializeStripe(); + } + + $: if (selectedPaymentMethodId) { + isStripeInitialized.set(false); + } + $: if (!show) { selectedPaymentMethodId = null; } From 1e19bd505f12adb9de9efcab226accab3796f1d2 Mon Sep 17 00:00:00 2001 From: Arman Date: Tue, 9 Apr 2024 09:53:08 +0200 Subject: [PATCH 28/46] fix: logic --- .../billing/replaceCard.svelte | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/routes/console/organization-[organization]/billing/replaceCard.svelte b/src/routes/console/organization-[organization]/billing/replaceCard.svelte index 92e1bd949..bf0f62916 100644 --- a/src/routes/console/organization-[organization]/billing/replaceCard.svelte +++ b/src/routes/console/organization-[organization]/billing/replaceCard.svelte @@ -21,18 +21,20 @@ onMount(async () => { methods = await sdk.forConsole.billing.listPaymentMethods(); - selectedPaymentMethodId = isBackup - ? $organization.backupPaymentMethodId - : $organization.paymentMethodId; + if (!$organization.paymentMethodId && !$organization.backupPaymentMethodId) { selectedPaymentMethodId = methods?.total ? methods.paymentMethods[0].$id : null; - } - // If the selected payment method does not belong to the current user, reset it - if ( - methods?.total && - !methods.paymentMethods.some((method) => method.$id === selectedPaymentMethodId) - ) { - selectedPaymentMethodId = null; + } else { + selectedPaymentMethodId = isBackup + ? $organization.backupPaymentMethodId + : $organization.paymentMethodId; + // If the selected payment method does not belong to the current user, select the first one. + if ( + methods?.total && + !methods.paymentMethods.some((method) => method.$id === selectedPaymentMethodId) + ) { + selectedPaymentMethodId = methods.paymentMethods[0].$id; + } } }); From d4d43b678b80fd5708926538009565441917d0df Mon Sep 17 00:00:00 2001 From: Arman Date: Tue, 9 Apr 2024 09:56:50 +0200 Subject: [PATCH 29/46] Update src/routes/console/project-[project]/updateVariables.svelte Co-authored-by: Steven Nguyen <1477010+stnguyen90@users.noreply.github.com> --- src/routes/console/project-[project]/updateVariables.svelte | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/routes/console/project-[project]/updateVariables.svelte b/src/routes/console/project-[project]/updateVariables.svelte index 892ed7ef4..035d4c480 100644 --- a/src/routes/console/project-[project]/updateVariables.svelte +++ b/src/routes/console/project-[project]/updateVariables.svelte @@ -139,9 +139,9 @@ showPromoteModal = false; await Promise.all([ - await invalidate(Dependencies.FUNCTION), - await invalidate(Dependencies.VARIABLES), - await invalidate(Dependencies.PROJECT_VARIABLES) + invalidate(Dependencies.FUNCTION), + invalidate(Dependencies.VARIABLES), + invalidate(Dependencies.PROJECT_VARIABLES) ]); addNotification({ From 4d88ef4dd5ea7fa191868a09f7db04d2a6d6ab2f Mon Sep 17 00:00:00 2001 From: Arman Date: Tue, 9 Apr 2024 10:01:01 +0200 Subject: [PATCH 30/46] chore: linter --- src/routes/console/project-[project]/updateVariables.svelte | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/routes/console/project-[project]/updateVariables.svelte b/src/routes/console/project-[project]/updateVariables.svelte index 035d4c480..7396219fa 100644 --- a/src/routes/console/project-[project]/updateVariables.svelte +++ b/src/routes/console/project-[project]/updateVariables.svelte @@ -139,9 +139,9 @@ showPromoteModal = false; await Promise.all([ - invalidate(Dependencies.FUNCTION), - invalidate(Dependencies.VARIABLES), - invalidate(Dependencies.PROJECT_VARIABLES) + invalidate(Dependencies.FUNCTION), + invalidate(Dependencies.VARIABLES), + invalidate(Dependencies.PROJECT_VARIABLES) ]); addNotification({ From d1514904cf83729718b410e7aaf4430104765149 Mon Sep 17 00:00:00 2001 From: Arman Date: Tue, 9 Apr 2024 10:23:55 +0200 Subject: [PATCH 31/46] chore: copy change from "delete" to "remove" --- .../billing/deleteOrgPayment.svelte | 13 ++++++------- .../billing/paymentMethods.svelte | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/routes/console/organization-[organization]/billing/deleteOrgPayment.svelte b/src/routes/console/organization-[organization]/billing/deleteOrgPayment.svelte index 747b538ec..e2de60520 100644 --- a/src/routes/console/organization-[organization]/billing/deleteOrgPayment.svelte +++ b/src/routes/console/organization-[organization]/billing/deleteOrgPayment.svelte @@ -58,11 +58,10 @@ headerDivider={false} title="Unable to delete payment method">

    - The {isBackup ? 'backup' : 'default'} payment method cannot be deleted as + The {isBackup ? 'backup' : 'default'} payment method cannot be removed as {$organization?.name} - has an upcoming invoice. To proceed with deletion, set a {isBackup - ? 'default' - : 'backup'} or add a new {isBackup ? 'backup' : 'default'} payment method. + has an upcoming invoice. To proceed, set a {isBackup ? 'default' : 'backup'} or add a new + {isBackup ? 'backup' : 'default'} payment method.

    @@ -76,13 +75,13 @@ icon="exclamation" state="warning" headerDivider={false} - title="Delete payment method"> + title="Remove payment method">

    - Are you sure you want to delete the payment method from {$organization?.name}? + Are you sure you want to remove the payment method from {$organization?.name}?

    - + {/if} diff --git a/src/routes/console/organization-[organization]/billing/paymentMethods.svelte b/src/routes/console/organization-[organization]/billing/paymentMethods.svelte index ae44de05e..5a41e40a7 100644 --- a/src/routes/console/organization-[organization]/billing/paymentMethods.svelte +++ b/src/routes/console/organization-[organization]/billing/paymentMethods.svelte @@ -137,7 +137,7 @@ showDelete = true; showDropdown = false; }}> - Delete + Remove
    From cd550315df9865e9e977c82cafbd50a342705807 Mon Sep 17 00:00:00 2001 From: Arman Date: Tue, 9 Apr 2024 15:34:12 +0200 Subject: [PATCH 32/46] fix: retry payment modal No method selected when the organization paymentMethod belongs to someone else --- .../billing/retryPaymentModal.svelte | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/routes/console/organization-[organization]/billing/retryPaymentModal.svelte b/src/routes/console/organization-[organization]/billing/retryPaymentModal.svelte index e0f034029..06dde940f 100644 --- a/src/routes/console/organization-[organization]/billing/retryPaymentModal.svelte +++ b/src/routes/console/organization-[organization]/billing/retryPaymentModal.svelte @@ -30,8 +30,21 @@ let paymentMethodId: string; let setAsDefault = false; - onMount(() => { - paymentMethodId = $organization.paymentMethodId; + onMount(async () => { + if (!$organization.paymentMethodId && !$organization.backupPaymentMethodId) { + paymentMethodId = $paymentMethods?.total ? $paymentMethods.paymentMethods[0].$id : null; + } else { + paymentMethodId = $organization.paymentMethodId + ? $organization.paymentMethodId + : $organization.backupPaymentMethodId; + // If the selected payment method does not belong to the current user, select the first one. + if ( + $paymentMethods?.total && + !$paymentMethods.paymentMethods.some((method) => method.$id === paymentMethodId) + ) { + paymentMethodId = $paymentMethods.paymentMethods[0].$id; + } + } }); async function handleSubmit() { From 01f1d4f6621707fdf19cf3c2fdca85777d9a5b5f Mon Sep 17 00:00:00 2001 From: Arman Date: Tue, 9 Apr 2024 16:26:55 +0200 Subject: [PATCH 33/46] chore: remove browser check --- src/lib/stores/billing.ts | 66 ++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index be97eab8a..3d827cf5c 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -27,7 +27,6 @@ import LimitReached from '$lib/components/billing/alerts/limitReached.svelte'; import { wizard } from './wizard'; import ChangeOrganizationTierCloud from '$routes/console/changeOrganizationTierCloud.svelte'; import { trackEvent } from '$lib/actions/analytics'; -import { browser } from '$app/environment'; export type Tier = 'tier-0' | 'tier-1' | 'tier-2'; @@ -216,42 +215,39 @@ export async function checkForUsageLimit(org: Organization) { }); } else if (resources.some((r) => r.value >= 75)) { readOnly.set(false); - if (browser) { - const lastNotification = - parseInt(localStorage.getItem('limitReachedNotification')) ?? 0; - const now = new Date().getTime(); - if (now - lastNotification < 1000 * 60 * 60 * 24) return; + const lastNotification = parseInt(localStorage.getItem('limitReachedNotification')) ?? 0; + const now = new Date().getTime(); + if (now - lastNotification < 1000 * 60 * 60 * 24) return; - localStorage.setItem('limitReachedNotification', now.toString()); - let message = `${org.name} has reached 75% of the Starter 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 ${org.name} has reached 75% of the Starter plan limit. Upgrade to ensure there are no service disruptions.`; - } - addNotification({ - type: 'warning', - isHtml: true, - timeout: 0, - message, - buttons: [ - { - name: 'View usage', - method: () => { - goto(`${base}/console/organization-${org.$id}/usage`); - } - }, - { - name: 'Upgrade plan', - method: () => { - wizard.start(ChangeOrganizationTierCloud); - trackEvent('click_organization_upgrade', { - from: 'button', - source: 'limit_reached_notification' - }); - } - } - ] - }); + localStorage.setItem('limitReachedNotification', now.toString()); + let message = `${org.name} has reached 75% of the Starter 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 ${org.name} has reached 75% of the Starter plan limit. Upgrade to ensure there are no service disruptions.`; } + addNotification({ + type: 'warning', + isHtml: true, + timeout: 0, + message, + buttons: [ + { + name: 'View usage', + method: () => { + goto(`${base}/console/organization-${org.$id}/usage`); + } + }, + { + name: 'Upgrade plan', + method: () => { + wizard.start(ChangeOrganizationTierCloud); + trackEvent('click_organization_upgrade', { + from: 'button', + source: 'limit_reached_notification' + }); + } + } + ] + }); } else { readOnly.set(false); } From 240eda2619d1212f36862c7eccc4444b8c7d8d0e Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 10 Apr 2024 15:35:20 +0200 Subject: [PATCH 34/46] chore: rename variable for more clarity --- src/lib/stores/billing.ts | 4 ++-- src/lib/system.ts | 2 +- src/routes/console/account/organizations/+page.svelte | 4 ++-- .../billing/planSummary.svelte | 6 +++--- .../console/organization-[organization]/header.svelte | 5 ++--- .../wizard/cloudOrganization/confirmDetails.svelte | 6 +++--- .../cloudOrganization/organizationDetails.svelte | 4 ++-- .../wizard/cloudOrganization/paymentDetails.svelte | 8 ++------ src/routes/console/wizard/cloudOrganization/store.ts | 4 ++-- .../cloudOrganizationChangeTier/choosePlan.svelte | 4 ++-- .../cloudOrganizationChangeTier/confirmDetails.svelte | 10 +++++----- .../wizard/cloudOrganizationChangeTier/store.ts | 4 ++-- 12 files changed, 28 insertions(+), 33 deletions(-) diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index 1a00cc840..1462f5125 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -10,7 +10,7 @@ import type { PlansMap, PaymentMethodData } from '$lib/sdk/billing'; -import { TRIAL_PERIOD_OVERRIDE, isCloud } from '$lib/system'; +import { IS_TRIAL_DISABLED, isCloud } from '$lib/system'; import { cachedStore } from '$lib/helpers/cache'; import { Query } from '@appwrite.io/console'; import { headerAlert } from './headerAlert'; @@ -169,7 +169,7 @@ export function isServiceLimited(serviceId: PlanServices, plan: Tier, total: num } export function calculateTrialDay(org: Organization) { - if (TRIAL_PERIOD_OVERRIDE) return; + if (IS_TRIAL_DISABLED) return; if (org?.billingPlan === BillingPlan.STARTER) return false; const endDate = new Date(org?.billingStartDate); const today = new Date(); diff --git a/src/lib/system.ts b/src/lib/system.ts index 521833161..adc04027e 100644 --- a/src/lib/system.ts +++ b/src/lib/system.ts @@ -24,4 +24,4 @@ export const isCloud = MODE === Mode.CLOUD; export const isSelfHosted = MODE !== Mode.CLOUD; export const hasStripePublicKey = !!VARS.STRIPE_PUBLIC_KEY; export const GRACE_PERIOD_OVERRIDE = false; -export const TRIAL_PERIOD_OVERRIDE = true; +export const IS_TRIAL_DISABLED = true; diff --git a/src/routes/console/account/organizations/+page.svelte b/src/routes/console/account/organizations/+page.svelte index 33b397915..be2b778a2 100644 --- a/src/routes/console/account/organizations/+page.svelte +++ b/src/routes/console/account/organizations/+page.svelte @@ -13,7 +13,7 @@ import CreateOrganization from '../../createOrganization.svelte'; import { sdk } from '$lib/stores/sdk'; import type { PageData } from './$types'; - import { TRIAL_PERIOD_OVERRIDE, isCloud } from '$lib/system'; + import { IS_TRIAL_DISABLED, isCloud } from '$lib/system'; import { Pill } from '$lib/elements'; import type { Models } from '@appwrite.io/console'; import type { Organization } from '$lib/stores/organization'; @@ -82,7 +82,7 @@ FREE
    {/if} - {#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.STARTER && !TRIAL_PERIOD_OVERRIDE} + {#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.STARTER && !IS_TRIAL_DISABLED}
    0 && - !TRIAL_PERIOD_OVERRIDE; + !IS_TRIAL_DISABLED; {#if $organization} @@ -56,7 +56,7 @@
    {tierToPlan($organization?.billingPlan)?.name} plan
    - {#if $organization?.billingPlan !== BillingPlan.STARTER && isTrial && !TRIAL_PERIOD_OVERRIDE} + {#if $organization?.billingPlan !== BillingPlan.STARTER && isTrial && !IS_TRIAL_DISABLED} TRIAL {/if}
    diff --git a/src/routes/console/organization-[organization]/header.svelte b/src/routes/console/organization-[organization]/header.svelte index 04213a412..7d8facfd9 100644 --- a/src/routes/console/organization-[organization]/header.svelte +++ b/src/routes/console/organization-[organization]/header.svelte @@ -19,8 +19,7 @@ } from '$lib/stores/organization'; import { wizard } from '$lib/stores/wizard'; import { GRACE_PERIOD_OVERRIDE, TRIAL_PERIOD_OVERRIDE, isCloud } from '$lib/system'; - import CreateOrganizationCloud from '../createOrganizationCloud.svelte'; - + import CreateOrganizationCloud from '../createOrganizationCloud.sveltIS_TRIAL_ENABLED let areMembersLimited: boolean; $: organization.subscribe(() => { const limit = getServiceLimit('members') || Infinity; @@ -102,7 +101,7 @@ $organization.billingStartDate )}. ${$daysLeftInTrial} days remaining.` }}> - TRIAL + TRIALIS_TRIAL_ENABLED {/if} diff --git a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte index 3be83c868..fac476d10 100644 --- a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte +++ b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte @@ -9,7 +9,7 @@ import type { Coupon } from '$lib/sdk/billing'; import { plansInfo } from '$lib/stores/billing'; import { sdk } from '$lib/stores/sdk'; - import { TRIAL_PERIOD_OVERRIDE } from '$lib/system'; + import { IS_TRIAL_DISABLED } from '$lib/system'; import { createOrganization, createOrganizationFinalAction } from './store'; const plan = $plansInfo?.get($createOrganization.billingPlan); @@ -54,7 +54,7 @@ Confirm your details - Confirm the details of your new organization{TRIAL_PERIOD_OVERRIDE + Confirm the details of your new organization{IS_TRIAL_DISABLED ? '.' : ' and start your free trial.'} @@ -126,7 +126,7 @@ {#if $createOrganization.billingPlan !== BillingPlan.STARTER}

    This amount, and any additional usage fees, will be charged on a recurring 30-day - billing cycle{TRIAL_PERIOD_OVERRIDE + billing cycle{IS_TRIAL_DISABLED ? '.' : ` after your trial period ends on ${toLocaleDate(billingPayDate.toString())}`}.

    diff --git a/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte b/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte index ef9231712..dfe8c80d6 100644 --- a/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte +++ b/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte @@ -8,7 +8,7 @@ import { plansInfo, tierFree, tierPro, tierScale } from '$lib/stores/billing'; import { organizationList, type Organization } from '$lib/stores/organization'; import { updateStepStatus } from '$lib/stores/wizard'; - import { TRIAL_PERIOD_OVERRIDE } from '$lib/system'; + import { IS_TRIAL_DISABLED } from '$lib/system'; import { createOrganization, createOrgSteps } from './store'; let showCustomId = false; @@ -109,7 +109,7 @@ {tierPro.description}

    - {#if !TRIAL_PERIOD_OVERRIDE} + {#if !IS_TRIAL_DISABLED} 14 DAY FREE TRIAL {/if} diff --git a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte index ed4c76719..023f42ad0 100644 --- a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte +++ b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte @@ -13,8 +13,7 @@ import { showUsageRatesModal } from '$lib/stores/billing'; import { PaymentBoxes } from '$lib/components/billing'; import { TRIAL_PERIOD_OVERRIDE } from '$lib/system'; - - const today = new Date(); +IS_TRIAL_ENABLEDnew Date(); const billingPayDate = new Date(today.getTime() + 44 * 24 * 60 * 60 * 1000); let methods: PaymentList; @@ -83,10 +82,7 @@ - - (new Map()); export const createOrganizationFinalAction = writable( - TRIAL_PERIOD_OVERRIDE ? 'Create' : 'Start trial' + IS_TRIAL_DISABLED ? 'Create' : 'Start trial' ); export const createOrganization = writable<{ diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte index da01e2449..d3fe6418b 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte @@ -15,8 +15,7 @@ import { formatCurrency } from '$lib/helpers/numbers'; import { TRIAL_PERIOD_OVERRIDE } from '$lib/system'; - let usage: OrganizationUsage = null; - let members: Models.MembershipList = null; + IS_TRIAL_ENABLED let members: Models.MembershipList = null; $: if ($changeOrganizationTier.billingPlan === BillingPlan.STARTER && $changeTierSteps) { $changeTierSteps = updateStepStatus($changeTierSteps, 2, true); @@ -142,6 +141,7 @@
  • + IS_TRIAL_ENABLED {:else} - + IS_TRIAL_ENABLED Confirm your details Confirm the details of your new organization{TRIAL_PERIOD_OVERRIDE @@ -126,8 +126,8 @@ {/if} - - {#if $changeOrganizationTier.billingPlan !== BillingPlan.STARTER} + IS_TRIAL_ENABLED{#if $changeOrganizationTier.billingPlan !== BillingPlan.STARTER} (new Map()); export const isUpgrade = writable(false); export const changeOrganizationFinalAction = writable( - TRIAL_PERIOD_OVERRIDE ? 'Create' : 'Start trial' + IS_TRIAL_DISABLED ? 'Create' : 'Start trial' ); export const changeOrganizationTier = writable<{ From 644a9d3f076874bd2b1f57d50dcfb7a4e142306c Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 10 Apr 2024 15:39:01 +0200 Subject: [PATCH 35/46] fix: issues and remove extra commas --- .../organization-[organization]/header.svelte | 9 ++-- .../cloudOrganization/confirmDetails.svelte | 2 +- .../cloudOrganization/paymentDetails.svelte | 14 +++--- .../choosePlan.svelte | 8 ++-- .../confirmDetails.svelte | 44 ++++++------------- 5 files changed, 33 insertions(+), 44 deletions(-) diff --git a/src/routes/console/organization-[organization]/header.svelte b/src/routes/console/organization-[organization]/header.svelte index 7d8facfd9..c77fecedf 100644 --- a/src/routes/console/organization-[organization]/header.svelte +++ b/src/routes/console/organization-[organization]/header.svelte @@ -18,8 +18,9 @@ organizationList } from '$lib/stores/organization'; import { wizard } from '$lib/stores/wizard'; - import { GRACE_PERIOD_OVERRIDE, TRIAL_PERIOD_OVERRIDE, isCloud } from '$lib/system'; - import CreateOrganizationCloud from '../createOrganizationCloud.sveltIS_TRIAL_ENABLED + import { GRACE_PERIOD_OVERRIDE, IS_TRIAL_DISABLED, isCloud } from '$lib/system'; + import CreateOrganizationCloud from '../createOrganizationCloud.svelte'; + let areMembersLimited: boolean; $: organization.subscribe(() => { const limit = getServiceLimit('members') || Infinity; @@ -93,7 +94,7 @@ {#if isCloud && $organization?.billingPlan === BillingPlan.STARTER} FREE {/if} - {#if isCloud && $organization?.billingTrialStartDate && $daysLeftInTrial > 0 && $organization.billingPlan !== BillingPlan.STARTER && !TRIAL_PERIOD_OVERRIDE} + {#if isCloud && $organization?.billingTrialStartDate && $daysLeftInTrial > 0 && $organization.billingPlan !== BillingPlan.STARTER && !IS_TRIAL_DISABLED}
    - TRIALIS_TRIAL_ENABLED + TRIAL
    {/if} diff --git a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte index fac476d10..00806f4ea 100644 --- a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte +++ b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte @@ -127,7 +127,7 @@

    This amount, and any additional usage fees, will be charged on a recurring 30-day billing cycle{IS_TRIAL_DISABLED - ? '.' + ? '' : ` after your trial period ends on ${toLocaleDate(billingPayDate.toString())}`}.

    {/if} diff --git a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte index 023f42ad0..5b03cee1e 100644 --- a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte +++ b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte @@ -12,8 +12,9 @@ import { toLocaleDate } from '$lib/helpers/date'; import { showUsageRatesModal } from '$lib/stores/billing'; import { PaymentBoxes } from '$lib/components/billing'; - import { TRIAL_PERIOD_OVERRIDE } from '$lib/system'; -IS_TRIAL_ENABLEDnew Date(); + import { IS_TRIAL_DISABLED } from '$lib/system'; + + const today = new Date(); const billingPayDate = new Date(today.getTime() + 44 * 24 * 60 * 60 * 1000); let methods: PaymentList; @@ -74,15 +75,18 @@ IS_TRIAL_ENABLEDnew Date(); Payment details - Add a payment method to your organization. {#if !TRIAL_PERIOD_OVERRIDE}You will not be - charged until your trial ends on {toLocaleDate(billingPayDate.toString())}. + Add a payment method to your organization. {#if !IS_TRIAL_DISABLED}You will not be charged + until your trial ends on {toLocaleDate(billingPayDate.toString())}. {/if} + +
  • - IS_TRIAL_ENABLED {#if $organization.billingPlan === BillingPlan.PRO} CURRENT PLAN - {:else if !TRIAL_PERIOD_OVERRIDE} + {:else if !IS_TRIAL_DISABLED} 14 DAY FREE TRIAL {/if} diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte index 7f29df8ee..dc5e16fb1 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte @@ -1,5 +1,5 @@ - + From becf053f33ccd6d864265bd02af944538d49fb83 Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 17 Apr 2024 12:04:55 +0200 Subject: [PATCH 42/46] chore: add tracking --- src/lib/layout/wizard.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/layout/wizard.svelte b/src/lib/layout/wizard.svelte index e8e525572..145926af6 100644 --- a/src/lib/layout/wizard.svelte +++ b/src/lib/layout/wizard.svelte @@ -97,6 +97,7 @@ $wizard.nextDisabled = true; if (finalMethod) { await finalMethod(); + trackEvent('wizard_finish'); $wizard.nextDisabled = false; } else { trackEvent('wizard_finish'); From 6d85d134ff6daf0674dbf52657b107dae8cfbcdf Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 17 Apr 2024 14:37:28 +0200 Subject: [PATCH 43/46] refactor: remove global variable and use backend data --- src/lib/sdk/billing.ts | 1 + src/lib/stores/billing.ts | 3 +-- src/lib/system.ts | 1 - .../console/account/organizations/+page.svelte | 6 +++--- .../billing/planSummary.svelte | 5 ++--- .../organization-[organization]/header.svelte | 12 +++++++++--- .../wizard/cloudOrganization/confirmDetails.svelte | 5 ++--- .../cloudOrganization/organizationDetails.svelte | 3 +-- .../wizard/cloudOrganization/paymentDetails.svelte | 9 +++++---- src/routes/console/wizard/cloudOrganization/store.ts | 8 ++++---- .../cloudOrganizationChangeTier/choosePlan.svelte | 5 ++--- .../confirmDetails.svelte | 7 ++++--- .../wizard/cloudOrganizationChangeTier/store.ts | 8 ++++---- 13 files changed, 38 insertions(+), 35 deletions(-) diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index d935bd84e..0dda5f294 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -261,6 +261,7 @@ export type Plan = { storage: AdditionalResource; users: AdditionalResource; }; + trialDays: number; }; export type PlansInfo = { diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index 1462f5125..fcdb3ab83 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -10,7 +10,7 @@ import type { PlansMap, PaymentMethodData } from '$lib/sdk/billing'; -import { IS_TRIAL_DISABLED, isCloud } from '$lib/system'; +import { isCloud } from '$lib/system'; import { cachedStore } from '$lib/helpers/cache'; import { Query } from '@appwrite.io/console'; import { headerAlert } from './headerAlert'; @@ -169,7 +169,6 @@ export function isServiceLimited(serviceId: PlanServices, plan: Tier, total: num } export function calculateTrialDay(org: Organization) { - if (IS_TRIAL_DISABLED) return; if (org?.billingPlan === BillingPlan.STARTER) return false; const endDate = new Date(org?.billingStartDate); const today = new Date(); diff --git a/src/lib/system.ts b/src/lib/system.ts index adc04027e..5cb998dca 100644 --- a/src/lib/system.ts +++ b/src/lib/system.ts @@ -24,4 +24,3 @@ export const isCloud = MODE === Mode.CLOUD; export const isSelfHosted = MODE !== Mode.CLOUD; export const hasStripePublicKey = !!VARS.STRIPE_PUBLIC_KEY; export const GRACE_PERIOD_OVERRIDE = false; -export const IS_TRIAL_DISABLED = true; diff --git a/src/routes/console/account/organizations/+page.svelte b/src/routes/console/account/organizations/+page.svelte index be2b778a2..33811a134 100644 --- a/src/routes/console/account/organizations/+page.svelte +++ b/src/routes/console/account/organizations/+page.svelte @@ -13,11 +13,11 @@ import CreateOrganization from '../../createOrganization.svelte'; import { sdk } from '$lib/stores/sdk'; import type { PageData } from './$types'; - import { IS_TRIAL_DISABLED, isCloud } from '$lib/system'; + import { isCloud } from '$lib/system'; import { Pill } from '$lib/elements'; import type { Models } from '@appwrite.io/console'; import type { Organization } from '$lib/stores/organization'; - import { daysLeftInTrial } from '$lib/stores/billing'; + import { daysLeftInTrial, plansInfo } from '$lib/stores/billing'; import { tooltip } from '$lib/actions/tooltip'; import { toLocaleDate } from '$lib/helpers/date'; import { wizard } from '$lib/stores/wizard'; @@ -82,7 +82,7 @@ FREE {/if} - {#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.STARTER && !IS_TRIAL_DISABLED} + {#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.STARTER && $plansInfo.get(organization.billingPlan)?.trialDays}
    0 && - !IS_TRIAL_DISABLED; + $plansInfo.get($organization.billingPlan)?.trialDays; {#if $organization} @@ -56,7 +55,7 @@
    {tierToPlan($organization?.billingPlan)?.name} plan
    - {#if $organization?.billingPlan !== BillingPlan.STARTER && isTrial && !IS_TRIAL_DISABLED} + {#if $organization?.billingPlan !== BillingPlan.STARTER && isTrial} TRIAL {/if}
    diff --git a/src/routes/console/organization-[organization]/header.svelte b/src/routes/console/organization-[organization]/header.svelte index c77fecedf..9b600ea44 100644 --- a/src/routes/console/organization-[organization]/header.svelte +++ b/src/routes/console/organization-[organization]/header.svelte @@ -9,7 +9,13 @@ import { toLocaleDate } from '$lib/helpers/date'; import { isTabSelected } from '$lib/helpers/load'; import { Cover } from '$lib/layout'; - import { daysLeftInTrial, getServiceLimit, readOnly, tierToPlan } from '$lib/stores/billing'; + import { + daysLeftInTrial, + getServiceLimit, + plansInfo, + readOnly, + tierToPlan + } from '$lib/stores/billing'; import { members, newMemberModal, @@ -18,7 +24,7 @@ organizationList } from '$lib/stores/organization'; import { wizard } from '$lib/stores/wizard'; - import { GRACE_PERIOD_OVERRIDE, IS_TRIAL_DISABLED, isCloud } from '$lib/system'; + import { GRACE_PERIOD_OVERRIDE, isCloud } from '$lib/system'; import CreateOrganizationCloud from '../createOrganizationCloud.svelte'; let areMembersLimited: boolean; @@ -94,7 +100,7 @@ {#if isCloud && $organization?.billingPlan === BillingPlan.STARTER} FREE {/if} - {#if isCloud && $organization?.billingTrialStartDate && $daysLeftInTrial > 0 && $organization.billingPlan !== BillingPlan.STARTER && !IS_TRIAL_DISABLED} + {#if isCloud && $organization?.billingTrialStartDate && $daysLeftInTrial > 0 && $organization.billingPlan !== BillingPlan.STARTER && $plansInfo.get($organization.billingPlan)?.trialDays}
    Confirm your details - Confirm the details of your new organization{IS_TRIAL_DISABLED + Confirm the details of your new organization{!plan.trialDays ? '.' : ' and start your free trial.'} @@ -126,7 +125,7 @@ {#if $createOrganization.billingPlan !== BillingPlan.STARTER}

    This amount, and any additional usage fees, will be charged on a recurring 30-day - billing cycle{IS_TRIAL_DISABLED + billing cycle{!plan.trialDays ? '' : ` after your trial period ends on ${toLocaleDate(billingPayDate.toString())}`}.

    diff --git a/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte b/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte index dfe8c80d6..67bed9a75 100644 --- a/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte +++ b/src/routes/console/wizard/cloudOrganization/organizationDetails.svelte @@ -8,7 +8,6 @@ import { plansInfo, tierFree, tierPro, tierScale } from '$lib/stores/billing'; import { organizationList, type Organization } from '$lib/stores/organization'; import { updateStepStatus } from '$lib/stores/wizard'; - import { IS_TRIAL_DISABLED } from '$lib/system'; import { createOrganization, createOrgSteps } from './store'; let showCustomId = false; @@ -109,7 +108,7 @@ {tierPro.description}

    - {#if !IS_TRIAL_DISABLED} + {#if proPlan?.trialDays} 14 DAY FREE TRIAL {/if} diff --git a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte index 5b03cee1e..956064b66 100644 --- a/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte +++ b/src/routes/console/wizard/cloudOrganization/paymentDetails.svelte @@ -10,9 +10,8 @@ import { initializeStripe, isStripeInitialized, submitStripeCard } from '$lib/stores/stripe'; import { sdk } from '$lib/stores/sdk'; import { toLocaleDate } from '$lib/helpers/date'; - import { showUsageRatesModal } from '$lib/stores/billing'; + import { plansInfo, showUsageRatesModal } from '$lib/stores/billing'; import { PaymentBoxes } from '$lib/components/billing'; - import { IS_TRIAL_DISABLED } from '$lib/system'; const today = new Date(); const billingPayDate = new Date(today.getTime() + 44 * 24 * 60 * 60 * 1000); @@ -75,8 +74,10 @@ Payment details - Add a payment method to your organization. {#if !IS_TRIAL_DISABLED}You will not be charged - until your trial ends on {toLocaleDate(billingPayDate.toString())}. + Add a payment method to your organization. {#if $plansInfo.get($createOrganization.billingPlan)?.trialDays}You + will not be charged until your trial ends on {toLocaleDate(billingPayDate.toString())}. {/if} diff --git a/src/routes/console/wizard/cloudOrganization/store.ts b/src/routes/console/wizard/cloudOrganization/store.ts index 73b050b60..f25d7d5f8 100644 --- a/src/routes/console/wizard/cloudOrganization/store.ts +++ b/src/routes/console/wizard/cloudOrganization/store.ts @@ -1,12 +1,12 @@ import { BillingPlan } from '$lib/constants'; import type { WizardStepsType } from '$lib/layout/wizard.svelte'; -import type { Tier } from '$lib/stores/billing'; -import { IS_TRIAL_DISABLED } from '$lib/system'; -import { writable } from 'svelte/store'; +import { plansInfo, type Tier } from '$lib/stores/billing'; +import { organization } from '$lib/stores/organization'; +import { get, writable } from 'svelte/store'; export const createOrgSteps = writable(new Map()); export const createOrganizationFinalAction = writable( - IS_TRIAL_DISABLED ? 'Create' : 'Start trial' + get(plansInfo)?.get(get(organization)?.billingPlan)?.trialDays ? 'Start trial' : 'Create' ); export const createOrganization = writable<{ diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte index ad1d62aa1..84b9ff788 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/choosePlan.svelte @@ -13,7 +13,6 @@ import { Pill } from '$lib/elements'; import { BillingPlan } from '$lib/constants'; import { formatCurrency } from '$lib/helpers/numbers'; - import { IS_TRIAL_DISABLED } from '$lib/system'; let usage: OrganizationUsage = null; let members: Models.MembershipList = null; @@ -162,8 +161,8 @@
    {#if $organization.billingPlan === BillingPlan.PRO} CURRENT PLAN - {:else if !IS_TRIAL_DISABLED} - 14 DAY FREE TRIAL + {:else if proPlan?.trialDays} + {proPlan?.trialDays} DAY FREE TRIAL {/if}
    diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte index dc5e16fb1..9b87670bf 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte @@ -16,7 +16,6 @@ feedbackDowngradeOptions, isUpgrade } from './store'; - import { IS_TRIAL_DISABLED } from '$lib/system'; const plan = $plansInfo.get($changeOrganizationTier.billingPlan); const collaboratorPrice = plan?.addons.member?.price ?? 0; @@ -78,7 +77,9 @@ Confirm your details - Confirm the details of your new organization{IS_TRIAL_DISABLED + Confirm the details of your new organization{!$plansInfo.get( + $changeOrganizationTier.billingPlan + )?.trialDays ? '.' : ' and start your free trial.'} @@ -147,7 +148,7 @@

    This amount, and any additional usage fees, will be charged on a recurring 30-day - billing cycle{IS_TRIAL_DISABLED + billing cycle{!$plansInfo.get($changeOrganizationTier.billingPlan)?.trialDays ? '' : ` after your trial period ends on ${toLocaleDate(billingPayDate.toString())}`}.

    diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts b/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts index 2c3ae0501..8d5fad783 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts @@ -1,13 +1,13 @@ import { BillingPlan } from '$lib/constants'; import type { WizardStepsType } from '$lib/layout/wizard.svelte'; -import type { Tier } from '$lib/stores/billing'; -import { IS_TRIAL_DISABLED } from '$lib/system'; -import { writable } from 'svelte/store'; +import { plansInfo, type Tier } from '$lib/stores/billing'; +import { organization } from '$lib/stores/organization'; +import { get, writable } from 'svelte/store'; export const changeTierSteps = writable(new Map()); export const isUpgrade = writable(false); export const changeOrganizationFinalAction = writable( - IS_TRIAL_DISABLED ? 'Create' : 'Start trial' + get(plansInfo)?.get(get(organization)?.billingPlan)?.trialDays ? 'Start trial' : 'Create' ); export const changeOrganizationTier = writable<{ From 16c1f6b39764f7318a4bdc8fb085636370f90d61 Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 17 Apr 2024 14:46:43 +0200 Subject: [PATCH 44/46] fix: plan final action text --- src/routes/console/+layout.svelte | 7 +++++-- .../wizard/cloudOrganization/confirmDetails.svelte | 7 +++++++ src/routes/console/wizard/cloudOrganization/store.ts | 9 +++------ .../cloudOrganizationChangeTier/confirmDetails.svelte | 4 ++++ .../console/wizard/cloudOrganizationChangeTier/store.ts | 9 +++------ 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/routes/console/+layout.svelte b/src/routes/console/+layout.svelte index dd45948cc..81fdcc85e 100644 --- a/src/routes/console/+layout.svelte +++ b/src/routes/console/+layout.svelte @@ -21,7 +21,8 @@ paymentExpired, checkForMarkedForDeletion, checkForMandate, - checkForMissingPaymentMethod + checkForMissingPaymentMethod, + plansInfo } from '$lib/stores/billing'; import { goto } from '$app/navigation'; import { CommandCenter, registerCommands, registerSearchers } from '$lib/commandCenter'; @@ -269,10 +270,12 @@ await checkForUsageLimit(org); checkForMarkedForDeletion(org); if (org?.billingPlan !== BillingPlan.STARTER) { - calculateTrialDay(org); await paymentExpired(org); await checkPaymentAuthorizationRequired(org); await checkForMandate(org); + if ($plansInfo.get(org.billingPlan)?.trialDays) { + calculateTrialDay(org); + } } } }); diff --git a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte index 214a2cc24..36b0ec6df 100644 --- a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte +++ b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte @@ -9,6 +9,7 @@ import type { Coupon } from '$lib/sdk/billing'; import { plansInfo } from '$lib/stores/billing'; import { sdk } from '$lib/stores/sdk'; + import { onMount } from 'svelte'; import { createOrganization, createOrganizationFinalAction } from './store'; const plan = $plansInfo?.get($createOrganization.billingPlan); @@ -18,6 +19,8 @@ const today = new Date(); const billingPayDate = new Date(today.getTime() + 44 * 24 * 60 * 60 * 1000); + onMount(() => {}); + let coupon: string = null; let couponData: Partial = { code: null, @@ -48,6 +51,10 @@ $: if ($createOrganization.billingPlan === BillingPlan.STARTER) { $createOrganizationFinalAction = 'Create organization'; } + + $: if (plan?.trialDays) { + $createOrganizationFinalAction = 'Start trial'; + } diff --git a/src/routes/console/wizard/cloudOrganization/store.ts b/src/routes/console/wizard/cloudOrganization/store.ts index f25d7d5f8..55a53175c 100644 --- a/src/routes/console/wizard/cloudOrganization/store.ts +++ b/src/routes/console/wizard/cloudOrganization/store.ts @@ -1,13 +1,10 @@ import { BillingPlan } from '$lib/constants'; import type { WizardStepsType } from '$lib/layout/wizard.svelte'; -import { plansInfo, type Tier } from '$lib/stores/billing'; -import { organization } from '$lib/stores/organization'; -import { get, writable } from 'svelte/store'; +import { type Tier } from '$lib/stores/billing'; +import { writable } from 'svelte/store'; export const createOrgSteps = writable(new Map()); -export const createOrganizationFinalAction = writable( - get(plansInfo)?.get(get(organization)?.billingPlan)?.trialDays ? 'Start trial' : 'Create' -); +export const createOrganizationFinalAction = writable('Create'); export const createOrganization = writable<{ id?: string; diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte index 9b87670bf..a0545d583 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/confirmDetails.svelte @@ -49,6 +49,10 @@ $: if (!$isUpgrade) { $changeOrganizationFinalAction = 'Confirm plan change'; } + + $: if (plan?.trialDays) { + $changeOrganizationFinalAction = 'Start trial'; + } {#if downgradeToStarter} diff --git a/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts b/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts index 8d5fad783..57463d106 100644 --- a/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts +++ b/src/routes/console/wizard/cloudOrganizationChangeTier/store.ts @@ -1,14 +1,11 @@ import { BillingPlan } from '$lib/constants'; import type { WizardStepsType } from '$lib/layout/wizard.svelte'; -import { plansInfo, type Tier } from '$lib/stores/billing'; -import { organization } from '$lib/stores/organization'; -import { get, writable } from 'svelte/store'; +import { type Tier } from '$lib/stores/billing'; +import { writable } from 'svelte/store'; export const changeTierSteps = writable(new Map()); export const isUpgrade = writable(false); -export const changeOrganizationFinalAction = writable( - get(plansInfo)?.get(get(organization)?.billingPlan)?.trialDays ? 'Start trial' : 'Create' -); +export const changeOrganizationFinalAction = writable('Create'); export const changeOrganizationTier = writable<{ billingPlan: Tier; From 5fe0e370aff6dd17a5a21aaa2a871347ac3f9ad5 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 26 Apr 2024 12:14:48 +0200 Subject: [PATCH 45/46] fix: error message --- src/hooks.client.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hooks.client.ts b/src/hooks.client.ts index 2345ffb2c..ad54c45cc 100644 --- a/src/hooks.client.ts +++ b/src/hooks.client.ts @@ -2,10 +2,11 @@ import { AppwriteException } from '@appwrite.io/console'; import type { HandleClientError } from '@sveltejs/kit'; export const handleError: HandleClientError = async ({ error, message, status }) => { - if (error instanceof AppwriteException && error.code === 0) { - status = undefined; + if (error instanceof AppwriteException) { + status = error.code === 0 ? undefined : error.code; message = error.message; } + return { message, status From cb937865cc58d7c3c42b8046a6971e02ab728548 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Fri, 26 Apr 2024 12:17:15 +0200 Subject: [PATCH 46/46] chore: remove unused code --- .../console/wizard/cloudOrganization/confirmDetails.svelte | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte index e3038c79d..e3eb21d55 100644 --- a/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte +++ b/src/routes/console/wizard/cloudOrganization/confirmDetails.svelte @@ -9,7 +9,6 @@ import type { Coupon } from '$lib/sdk/billing'; import { plansInfo } from '$lib/stores/billing'; import { sdk } from '$lib/stores/sdk'; - import { onMount } from 'svelte'; import { createOrganization, createOrganizationFinalAction } from './store'; const plan = $plansInfo?.get($createOrganization.billingPlan); @@ -19,8 +18,6 @@ const today = new Date(); const billingPayDate = new Date(today.getTime() + 44 * 24 * 60 * 60 * 1000); - onMount(() => {}); - let coupon: string = null; let couponData: Partial = { code: null,