From c67fea49824e3c541c46aeaf578a4b81b348f84e Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 28 Aug 2024 02:57:28 +0000 Subject: [PATCH 001/231] update create --- src/lib/sdk/billing.ts | 8 ++- .../console/create-organization/+page.svelte | 51 ++++++++----------- 2 files changed, 27 insertions(+), 32 deletions(-) diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index f0fd8ec089..ebe2a55571 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -307,7 +307,9 @@ export class Billing { name: string, billingPlan: string, paymentMethodId: string, - billingAddressId: string = undefined + billingAddressId: string = undefined, + couponId: string = undefined, + invites: Array = [] ): Promise { const path = `/organizations`; const params = { @@ -315,7 +317,9 @@ export class Billing { name, billingPlan, paymentMethodId, - billingAddressId + billingAddressId, + couponId, + invites }; const uri = new URL(this.client.config.endpoint + path); return await this.client.call( diff --git a/src/routes/console/create-organization/+page.svelte b/src/routes/console/create-organization/+page.svelte index e7ac26659d..1b9dd8b458 100644 --- a/src/routes/console/create-organization/+page.svelte +++ b/src/routes/console/create-organization/+page.svelte @@ -103,23 +103,14 @@ null ); } else { - // Create free organization if coming from onboarding - if (previousPage.includes('/console/onboarding') && !anyOrgFree) { - await sdk.forConsole.billing.createOrganization( - ID.unique(), - 'Personal Projects', - BillingPlan.FREE, - null, - null - ); - } - org = await sdk.forConsole.billing.createOrganization( ID.unique(), name, billingPlan, paymentMethodId, - null + null, + couponData?.code, + collaborators ); //Add budget @@ -127,25 +118,25 @@ await sdk.forConsole.billing.updateBudget(org.$id, billingBudget, [75]); } - //Add coupon - if (couponData?.code) { - await sdk.forConsole.billing.addCredit(org.$id, couponData.code); - trackEvent(Submit.CreditRedeem); - } + // //Add coupon + // if (couponData?.code) { + // await sdk.forConsole.billing.addCredit(org.$id, couponData.code); + // trackEvent(Submit.CreditRedeem); + // } - //Add collaborators - if (collaborators?.length) { - collaborators.forEach(async (collaborator) => { - await sdk.forConsole.teams.createMembership( - org.$id, - ['owner'], - collaborator, - undefined, - undefined, - `${$page.url.origin}/console/organization-${org.$id}` - ); - }); - } + // //Add collaborators + // if (collaborators?.length) { + // collaborators.forEach(async (collaborator) => { + // await sdk.forConsole.teams.createMembership( + // org.$id, + // ['owner'], + // collaborator, + // undefined, + // undefined, + // `${$page.url.origin}/console/organization-${org.$id}` + // ); + // }); + // } // Add tax ID if (taxId) { From 708517a0d075ee90e7706770e388a455b5635ae5 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 28 Aug 2024 11:08:18 +0545 Subject: [PATCH 002/231] authorize payment --- .../commandCenter/searchers/organizations.ts | 2 +- src/lib/sdk/billing.ts | 4 ++-- src/lib/stores/organization.ts | 9 ++++++++ src/routes/+layout.ts | 2 +- .../console/account/organizations/+page.ts | 2 +- .../console/create-organization/+page.svelte | 21 ++++++++++++++++--- 6 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/lib/commandCenter/searchers/organizations.ts b/src/lib/commandCenter/searchers/organizations.ts index df72d77b26..e5e8d76940 100644 --- a/src/lib/commandCenter/searchers/organizations.ts +++ b/src/lib/commandCenter/searchers/organizations.ts @@ -3,7 +3,7 @@ import { sdk } from '$lib/stores/sdk'; import type { Searcher } from '../commands'; export const orgSearcher = (async (query: string) => { - const { teams } = await sdk.forConsole.teams.list(); + const { teams } = await sdk.forConsole.billing.listOrganization(); return teams .filter((organization) => organization.name.toLowerCase().includes(query.toLowerCase())) .map((organization) => { diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index ebe2a55571..ea278c5bac 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -1,5 +1,5 @@ import type { Client, Models } from '@appwrite.io/console'; -import type { Organization, OrganizationList } from '../stores/organization'; +import type { CreateOrgAuth, Organization, OrganizationList } from '../stores/organization'; import type { PaymentMethod } from '@stripe/stripe-js'; import type { Tier } from '$lib/stores/billing'; @@ -310,7 +310,7 @@ export class Billing { billingAddressId: string = undefined, couponId: string = undefined, invites: Array = [] - ): Promise { + ): Promise { const path = `/organizations`; const params = { organizationId, diff --git a/src/lib/stores/organization.ts b/src/lib/stores/organization.ts index 2beb13b03c..d41cc3f54a 100644 --- a/src/lib/stores/organization.ts +++ b/src/lib/stores/organization.ts @@ -3,6 +3,15 @@ import { derived, writable } from 'svelte/store'; import type { Models } from '@appwrite.io/console'; import type { Tier } from './billing'; +export type CreateOrgAuth = { + status: number; + message: string; + teamId: string; + invoiceId: string; + clientSecret: string; + type: string; +}; + export type Organization = Models.Team> & { billingBudget: number; billingPlan: Tier; diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 85ad4e83d9..5f0472229f 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -22,7 +22,7 @@ export const load: LayoutLoad = async ({ depends, url }) => { return { account, - organizations: await sdk.forConsole.teams.list() + organizations: await sdk.forConsole.billing.listOrganization() }; } catch (error) { const acceptedRoutes = [ diff --git a/src/routes/console/account/organizations/+page.ts b/src/routes/console/account/organizations/+page.ts index 0b89b1d302..3f21115b89 100644 --- a/src/routes/console/account/organizations/+page.ts +++ b/src/routes/console/account/organizations/+page.ts @@ -12,7 +12,7 @@ export const load: PageLoad = async ({ url, route }) => { return { offset, limit, - organizations: await sdk.forConsole.teams.list([ + organizations: await sdk.forConsole.billing.listOrganization([ Query.offset(offset), Query.limit(limit), Query.orderDesc('') diff --git a/src/routes/console/create-organization/+page.svelte b/src/routes/console/create-organization/+page.svelte index 1b9dd8b458..3bcbae0413 100644 --- a/src/routes/console/create-organization/+page.svelte +++ b/src/routes/console/create-organization/+page.svelte @@ -22,8 +22,13 @@ import type { Coupon, PaymentList } from '$lib/sdk/billing'; import { plansInfo, tierFree, tierPro, tierToPlan } from '$lib/stores/billing'; import { addNotification } from '$lib/stores/notifications'; - import { organizationList, type Organization } from '$lib/stores/organization'; + import { + organizationList, + type CreateOrgAuth, + type Organization + } from '$lib/stores/organization'; import { sdk } from '$lib/stores/sdk'; + import { confirmPayment } from '$lib/stores/stripe'; import { ID } from '@appwrite.io/console'; import { onMount } from 'svelte'; import { writable } from 'svelte/store'; @@ -90,9 +95,13 @@ paymentMethodId = methods.paymentMethods.find((method) => !!method?.last4)?.$id ?? null; } + function isOrganization(org: Organization | CreateOrgAuth): org is Organization { + return (org as Organization).$id !== undefined; + } + async function create() { try { - let org: Organization; + let org: Organization | CreateOrgAuth; if (billingPlan === BillingPlan.FREE) { org = await sdk.forConsole.billing.createOrganization( @@ -113,8 +122,14 @@ collaborators ); + if (!isOrganization(org) && org.status == 402) { + let clientSecret = org.clientSecret; + await confirmPayment('', clientSecret, paymentMethodId); + // throw new Error('Payment requires authentication'); + } + //Add budget - if (billingBudget) { + if (billingBudget && isOrganization(org)) { await sdk.forConsole.billing.updateBudget(org.$id, billingBudget, [75]); } From eec5c6f1f34b5fb5e0d788166a3e92eae9819ef5 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Thu, 29 Aug 2024 08:30:49 +0545 Subject: [PATCH 003/231] support taxid and budget while creating --- src/lib/sdk/billing.ts | 8 ++++++-- .../console/create-organization/+page.svelte | 16 +++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index ea278c5bac..936d9f3ad8 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -309,7 +309,9 @@ export class Billing { paymentMethodId: string, billingAddressId: string = undefined, couponId: string = undefined, - invites: Array = [] + invites: Array = [], + budget: number = undefined, + taxId: string = undefined ): Promise { const path = `/organizations`; const params = { @@ -319,7 +321,9 @@ export class Billing { paymentMethodId, billingAddressId, couponId, - invites + invites, + budget, + taxId }; const uri = new URL(this.client.config.endpoint + path); return await this.client.call( diff --git a/src/routes/console/create-organization/+page.svelte b/src/routes/console/create-organization/+page.svelte index 3bcbae0413..09c9e9248b 100644 --- a/src/routes/console/create-organization/+page.svelte +++ b/src/routes/console/create-organization/+page.svelte @@ -119,7 +119,9 @@ paymentMethodId, null, couponData?.code, - collaborators + collaborators, + billingBudget, + taxId ); if (!isOrganization(org) && org.status == 402) { @@ -129,9 +131,9 @@ } //Add budget - if (billingBudget && isOrganization(org)) { - await sdk.forConsole.billing.updateBudget(org.$id, billingBudget, [75]); - } + // if (billingBudget && isOrganization(org)) { + // await sdk.forConsole.billing.updateBudget(org.$id, billingBudget, [75]); + // } // //Add coupon // if (couponData?.code) { @@ -154,9 +156,9 @@ // } // Add tax ID - if (taxId) { - await sdk.forConsole.billing.updateTaxId(org.$id, taxId); - } + // if (taxId) { + // await sdk.forConsole.billing.updateTaxId(org.$id, taxId); + // } } trackEvent(Submit.OrganizationCreate, { From 414bc60bc88ef93dd87c4023dde3e7e55898c0b1 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Thu, 29 Aug 2024 11:26:22 +0545 Subject: [PATCH 004/231] handle validation --- src/lib/sdk/billing.ts | 26 ++++++++- src/lib/stores/stripe.ts | 10 +++- .../console/create-organization/+page.svelte | 56 ++++++++++++++++--- .../billing/paymentHistory.svelte | 1 - 4 files changed, 77 insertions(+), 16 deletions(-) diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index 936d9f3ad8..646fdc1752 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -302,16 +302,36 @@ export class Billing { ); } + async validateOrganization( + organizationId: string, + invites: string[], + ): Promise { + const path = `/organizations/${organizationId}/validate`; + const params = { + organizationId, + invites, + }; + const uri = new URL(this.client.config.endpoint + path); + return await this.client.call( + 'PATCH', + uri, + { + 'content-type': 'application/json' + }, + params + ); + } + async createOrganization( organizationId: string, name: string, billingPlan: string, paymentMethodId: string, - billingAddressId: string = undefined, - couponId: string = undefined, + billingAddressId: string = null, + couponId: string = null, invites: Array = [], budget: number = undefined, - taxId: string = undefined + taxId: string = null ): Promise { const path = `/organizations`; const params = { diff --git a/src/lib/stores/stripe.ts b/src/lib/stores/stripe.ts index 93b4576aec..b1f01016b8 100644 --- a/src/lib/stores/stripe.ts +++ b/src/lib/stores/stripe.ts @@ -116,7 +116,8 @@ export async function confirmPayment( orgId: string, clientSecret: string, paymentMethodId: string, - route?: string + route?: string, + returnError: boolean = false ) { try { const url = @@ -128,10 +129,13 @@ export async function confirmPayment( clientSecret: clientSecret, confirmParams: { return_url: url, - payment_method: paymentMethod.providerMethodId - } + payment_method: paymentMethod.providerMethodId, + }, }); if (error) { + if (returnError) { + return error; + } throw error.message; } } catch (e) { diff --git a/src/routes/console/create-organization/+page.svelte b/src/routes/console/create-organization/+page.svelte index 09c9e9248b..67d1341f15 100644 --- a/src/routes/console/create-organization/+page.svelte +++ b/src/routes/console/create-organization/+page.svelte @@ -88,6 +88,14 @@ if (anyOrgFree) { billingPlan = BillingPlan.PRO; } + if($page.url.searchParams.has('type')) { + const type = $page.url.searchParams.get('type'); + if(type === 'confirmed') { + const organizationId= $page.url.searchParams.get('id'); + const invites = $page.url.searchParams.getAll('invites'); + await validate(organizationId, invites); + } + } }); async function loadPaymentMethods() { @@ -99,6 +107,27 @@ return (org as Organization).$id !== undefined; } + async function validate(organizationId: string, invites: string[]) { + try { + let org = await sdk.forConsole.billing.validateOrganization(organizationId, invites); + if (isOrganization(org)) { + await preloadData(`${base}/console/organization-${org.$id}`); + await goto(`${base}/console/organization-${org.$id}`); + addNotification({ + type: 'success', + message: `${org.name ?? 'Organization'} has been created` + }); + } + } catch (e) { + addNotification({ + type: 'error', + message: e.message + }); + trackError(e, Submit.OrganizationCreate); + } + + } + async function create() { try { let org: Organization | CreateOrgAuth; @@ -126,8 +155,15 @@ if (!isOrganization(org) && org.status == 402) { let clientSecret = org.clientSecret; - await confirmPayment('', clientSecret, paymentMethodId); - // throw new Error('Payment requires authentication'); + let params = new URLSearchParams(); + params.append('type', 'confirmed'); + params.append('id', org.teamId); + for (let index = 0; index < collaborators.length; index++) { + const invite = collaborators[index]; + params.append('invites', invite); + } + await confirmPayment('', clientSecret, paymentMethodId, '/console/create-organization?'+params.toString()); + await validate(org.teamId, collaborators); } //Add budget @@ -167,13 +203,15 @@ members_invited: collaborators?.length }); - await invalidate(Dependencies.ACCOUNT); - await preloadData(`${base}/console/organization-${org.$id}`); - await goto(`${base}/console/organization-${org.$id}`); - addNotification({ - type: 'success', - message: `${name ?? 'Organization'} has been created` - }); + if(isOrganization(org)) { + await invalidate(Dependencies.ACCOUNT); + await preloadData(`${base}/console/organization-${org.$id}`); + await goto(`${base}/console/organization-${org.$id}`); + addNotification({ + type: 'success', + message: `${org.name ?? 'Organization'} has been created` + }); + } } catch (e) { addNotification({ type: 'error', diff --git a/src/routes/console/organization-[organization]/billing/paymentHistory.svelte b/src/routes/console/organization-[organization]/billing/paymentHistory.svelte index 1784b0a57d..0c9642dfca 100644 --- a/src/routes/console/organization-[organization]/billing/paymentHistory.svelte +++ b/src/routes/console/organization-[organization]/billing/paymentHistory.svelte @@ -49,7 +49,6 @@ invoiceList = await sdk.forConsole.billing.listInvoices($page.params.organization, [ Query.limit(limit), Query.offset(offset), - Query.notEqual('from', $organization.billingCurrentInvoiceDate), Query.orderDesc('$createdAt') ]); } From c97e372386764d6cd456e9cf776368f1c4f3fa26 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 3 Sep 2024 09:17:18 +0545 Subject: [PATCH 005/231] fix check with cloud --- src/lib/sdk/billing.ts | 4 +- src/lib/stores/organization.ts | 2 +- src/routes/+layout.ts | 3 +- .../console/account/organizations/+page.ts | 15 ++++-- .../console/create-organization/+page.svelte | 52 +++++-------------- 5 files changed, 28 insertions(+), 48 deletions(-) diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index 646fdc1752..3c93d32aec 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -1,5 +1,5 @@ import type { Client, Models } from '@appwrite.io/console'; -import type { CreateOrgAuth, Organization, OrganizationList } from '../stores/organization'; +import type { OrganizationError, Organization, OrganizationList } from '../stores/organization'; import type { PaymentMethod } from '@stripe/stripe-js'; import type { Tier } from '$lib/stores/billing'; @@ -332,7 +332,7 @@ export class Billing { invites: Array = [], budget: number = undefined, taxId: string = null - ): Promise { + ): Promise { const path = `/organizations`; const params = { organizationId, diff --git a/src/lib/stores/organization.ts b/src/lib/stores/organization.ts index d41cc3f54a..ca7269ca37 100644 --- a/src/lib/stores/organization.ts +++ b/src/lib/stores/organization.ts @@ -3,7 +3,7 @@ import { derived, writable } from 'svelte/store'; import type { Models } from '@appwrite.io/console'; import type { Tier } from './billing'; -export type CreateOrgAuth = { +export type OrganizationError = { status: number; message: string; teamId: string; diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 5f0472229f..8986f1a126 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -6,6 +6,7 @@ import { redirect } from '@sveltejs/kit'; import { Dependencies } from '$lib/constants'; import type { LayoutLoad } from './$types'; import { redirectTo } from './store'; +import { isCloud } from '$lib/system'; export const ssr = false; @@ -22,7 +23,7 @@ export const load: LayoutLoad = async ({ depends, url }) => { return { account, - organizations: await sdk.forConsole.billing.listOrganization() + organizations: isCloud ? await sdk.forConsole.billing.listOrganization() : await sdk.forConsole.teams.list() }; } catch (error) { const acceptedRoutes = [ diff --git a/src/routes/console/account/organizations/+page.ts b/src/routes/console/account/organizations/+page.ts index 3f21115b89..803497c6a8 100644 --- a/src/routes/console/account/organizations/+page.ts +++ b/src/routes/console/account/organizations/+page.ts @@ -3,19 +3,24 @@ import { sdk } from '$lib/stores/sdk'; import { getLimit, getPage, pageToOffset } from '$lib/helpers/load'; import { CARD_LIMIT } from '$lib/constants'; import type { PageLoad } from './$types'; +import { isCloud } from '$lib/system'; export const load: PageLoad = async ({ url, route }) => { const page = getPage(url); const limit = getLimit(url, route, CARD_LIMIT); const offset = pageToOffset(page, limit); + const queries = [ + Query.offset(offset), + Query.limit(limit), + Query.orderDesc('') + ]; + + const organizations = isCloud ? await sdk.forConsole.billing.listOrganization(queries) : sdk.forConsole.teams.list(queries); + return { offset, limit, - organizations: await sdk.forConsole.billing.listOrganization([ - Query.offset(offset), - Query.limit(limit), - Query.orderDesc('') - ]) + organizations }; }; diff --git a/src/routes/console/create-organization/+page.svelte b/src/routes/console/create-organization/+page.svelte index 67d1341f15..323d48c610 100644 --- a/src/routes/console/create-organization/+page.svelte +++ b/src/routes/console/create-organization/+page.svelte @@ -24,7 +24,7 @@ import { addNotification } from '$lib/stores/notifications'; import { organizationList, - type CreateOrgAuth, + type OrganizationError, type Organization } from '$lib/stores/organization'; import { sdk } from '$lib/stores/sdk'; @@ -88,10 +88,10 @@ if (anyOrgFree) { billingPlan = BillingPlan.PRO; } - if($page.url.searchParams.has('type')) { + if ($page.url.searchParams.has('type')) { const type = $page.url.searchParams.get('type'); - if(type === 'confirmed') { - const organizationId= $page.url.searchParams.get('id'); + if (type === 'confirmed') { + const organizationId = $page.url.searchParams.get('id'); const invites = $page.url.searchParams.getAll('invites'); await validate(organizationId, invites); } @@ -103,7 +103,7 @@ paymentMethodId = methods.paymentMethods.find((method) => !!method?.last4)?.$id ?? null; } - function isOrganization(org: Organization | CreateOrgAuth): org is Organization { + function isOrganization(org: Organization | OrganizationError): org is Organization { return (org as Organization).$id !== undefined; } @@ -125,12 +125,11 @@ }); trackError(e, Submit.OrganizationCreate); } - } async function create() { try { - let org: Organization | CreateOrgAuth; + let org: Organization | OrganizationError; if (billingPlan === BillingPlan.FREE) { org = await sdk.forConsole.billing.createOrganization( @@ -162,39 +161,14 @@ const invite = collaborators[index]; params.append('invites', invite); } - await confirmPayment('', clientSecret, paymentMethodId, '/console/create-organization?'+params.toString()); + await confirmPayment( + '', + clientSecret, + paymentMethodId, + '/console/create-organization?' + params.toString() + ); await validate(org.teamId, collaborators); } - - //Add budget - // if (billingBudget && isOrganization(org)) { - // await sdk.forConsole.billing.updateBudget(org.$id, billingBudget, [75]); - // } - - // //Add coupon - // if (couponData?.code) { - // await sdk.forConsole.billing.addCredit(org.$id, couponData.code); - // trackEvent(Submit.CreditRedeem); - // } - - // //Add collaborators - // if (collaborators?.length) { - // collaborators.forEach(async (collaborator) => { - // await sdk.forConsole.teams.createMembership( - // org.$id, - // ['owner'], - // collaborator, - // undefined, - // undefined, - // `${$page.url.origin}/console/organization-${org.$id}` - // ); - // }); - // } - - // Add tax ID - // if (taxId) { - // await sdk.forConsole.billing.updateTaxId(org.$id, taxId); - // } } trackEvent(Submit.OrganizationCreate, { @@ -203,7 +177,7 @@ members_invited: collaborators?.length }); - if(isOrganization(org)) { + if (isOrganization(org)) { await invalidate(Dependencies.ACCOUNT); await preloadData(`${base}/console/organization-${org.$id}`); await goto(`${base}/console/organization-${org.$id}`); From b568e8553c5eae5a308073a78815015e6e329820 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 3 Sep 2024 09:19:07 +0545 Subject: [PATCH 006/231] improve --- src/routes/console/create-organization/+page.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/console/create-organization/+page.svelte b/src/routes/console/create-organization/+page.svelte index 323d48c610..8dc928f004 100644 --- a/src/routes/console/create-organization/+page.svelte +++ b/src/routes/console/create-organization/+page.svelte @@ -90,7 +90,7 @@ } if ($page.url.searchParams.has('type')) { const type = $page.url.searchParams.get('type'); - if (type === 'confirmed') { + if (type === 'payment_confirmed') { const organizationId = $page.url.searchParams.get('id'); const invites = $page.url.searchParams.getAll('invites'); await validate(organizationId, invites); @@ -155,7 +155,7 @@ if (!isOrganization(org) && org.status == 402) { let clientSecret = org.clientSecret; let params = new URLSearchParams(); - params.append('type', 'confirmed'); + params.append('type', 'payment_confirmed'); params.append('id', org.teamId); for (let index = 0; index < collaborators.length; index++) { const invite = collaborators[index]; From 81d4ad8a6e2a5939edd15ffd5298f20e0ecdcbe1 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 11 Nov 2024 08:41:25 +0000 Subject: [PATCH 007/231] remove unused --- .../organization-[organization]/billing/paymentHistory.svelte | 1 - 1 file changed, 1 deletion(-) diff --git a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte index 290b76b75b..e74739f537 100644 --- a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte +++ b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte @@ -28,7 +28,6 @@ import { onMount } from 'svelte'; import { trackEvent } from '$lib/actions/analytics'; import { selectedInvoice, showRetryModal } from './store'; - import { organization } from '$lib/stores/organization'; let showDropdown = []; let showFailedError = false; From c7a9e26de0ee343bc66e835b58533d5c7ec23ff9 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 11 Nov 2024 09:05:36 +0000 Subject: [PATCH 008/231] allow scale selection --- .../components/billing/planSelection.svelte | 50 +++++++++---------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/lib/components/billing/planSelection.svelte b/src/lib/components/billing/planSelection.svelte index 0d484a9b40..cfcb28bbab 100644 --- a/src/lib/components/billing/planSelection.svelte +++ b/src/lib/components/billing/planSelection.svelte @@ -76,31 +76,29 @@ - {#if $organization?.billingPlan === BillingPlan.SCALE} -
  • - - -
    -

    - {tierScale.name} - {#if $organization?.billingPlan === BillingPlan.SCALE && !isNewOrg} - Current plan - {/if} -

    -

    - {tierScale.description} -

    -

    - {formatCurrency(scalePlan?.price ?? 0)} per month + usage -

    -
    -
    -
    -
  • - {/if} +
  • + + +
    +

    + {tierScale.name} + {#if $organization?.billingPlan === BillingPlan.SCALE && !isNewOrg} + Current plan + {/if} +

    +

    + {tierScale.description} +

    +

    + {formatCurrency(scalePlan?.price ?? 0)} per month + usage +

    +
    +
    +
    +
  • {/if} From f29ca9a8e9776e643aad723c268bb549d1a63f34 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Thu, 14 Nov 2024 12:59:39 +0545 Subject: [PATCH 009/231] update plan upgrade --- src/lib/sdk/billing.ts | 14 ++- .../change-plan/+page.svelte | 116 +++++++++++------- 2 files changed, 86 insertions(+), 44 deletions(-) diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index f2428fd19d..bee94ffc3b 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -416,14 +416,22 @@ export class Billing { organizationId: string, billingPlan: string, paymentMethodId: string, - billingAddressId: string = undefined - ): Promise { + billingAddressId: string = undefined, + couponId: string = null, + invites: Array = [], + budget: number = undefined, + taxId: string = null + ): Promise { const path = `/organizations/${organizationId}/plan`; const params = { organizationId, billingPlan, paymentMethodId, - billingAddressId + billingAddressId, + couponId, + invites, + budget, + taxId }; const uri = new URL(this.client.config.endpoint + path); return await this.client.call( diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index 3682491c7f..573f1e9fb2 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -1,5 +1,5 @@
    - -

    {currentPlan.name} plan

    -

    {formatCurrency(currentPlan.price)}

    -
    - +
    +

    {selectedPlan.name} plan

    +

    {formatCurrency(selectedPlan.price)}

    +
    + +

    Additional seats ({collaborators?.length})

    - {formatCurrency(extraSeatsCost)} + {formatCurrency( + isScaleDowngrade + ? (collaborators?.length ?? 0) * (selectedPlan?.addons?.member?.price ?? 0) + : extraSeatsCost + )}

    - +
    + + {#if isScaleUpgrade} + {@const currentPlanName = currentOrgPlan.name} +
    +
    + Unused {currentPlanName} plan balance + + +
    +

    -{formatCurrency(unUsedBalances)}

    +
    + {:else if isScaleDowngrade} +
    + Unused {currentOrgPlan.name} plan balance +

    -{formatCurrency(currentOrgPlan.price)}

    +
    + {/if} + {#if couponData?.status === 'active'} {/if}
    - +

    Upcoming charge
    Due on {!currentPlan.trialDays + >Due on {!selectedPlan.trialDays ? toLocaleDate(billingPayDate.toString()) : toLocaleDate(trialEndDate.toString())}

    {formatCurrency(estimatedTotal)}

    - +

    - You'll pay {formatCurrency(estimatedTotal)} now, with our first - billing cycle starting on + You'll {isRefund ? 'receive a refund of' : 'pay'} + {formatCurrency(estimatedTotal)} + now, with our first billing cycle starting on {!currentPlan.trialDays + >{!selectedPlan.trialDays ? toLocaleDate(billingPayDate.toString()) : toLocaleDate(trialEndDate.toString())}. Once your credits run out, you'll be charged - {formatCurrency(currentPlan.price)} plus usage fees every 30 days. + {formatCurrency(selectedPlan.price)} plus usage fees every 30 days.

    diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index fe317b18a4..46c1e8b59e 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -23,7 +23,7 @@ InputTextarea, Label } from '$lib/elements/forms'; - import { formatCurrency } from '$lib/helpers/numbers.js'; + import { formatCurrency } from '$lib/helpers/numbers'; import { WizardSecondaryContainer, WizardSecondaryContent, @@ -39,7 +39,7 @@ type OrganizationError } from '$lib/stores/organization'; import { sdk } from '$lib/stores/sdk'; - import { confirmPayment } from '$lib/stores/stripe.js'; + import { confirmPayment } from '$lib/stores/stripe'; import { user } from '$lib/stores/user'; import { VARS } from '$lib/system'; import { onMount } from 'svelte'; @@ -107,8 +107,8 @@ billingPlan = BillingPlan.PRO; } - const currentPlan = await sdk.forConsole.billing.getPlan($organization?.$id); - selfService = currentPlan.selfService; + const currentOrgPlan = await sdk.forConsole.billing.getPlan($organization?.$id); + selfService = currentOrgPlan.selfService; }); async function loadPaymentMethods() { @@ -210,7 +210,7 @@ async function upgrade() { try { //Add collaborators - var newCollaborators = []; + let newCollaborators = []; if (collaborators?.length) { newCollaborators = collaborators.filter( (collaborator) => @@ -369,11 +369,12 @@ {#if billingPlan !== BillingPlan.FREE && $organization.billingPlan !== billingPlan && $organization.billingPlan !== BillingPlan.CUSTOM} + currentTier={$organization.billingPlan} /> {:else if $organization.billingPlan !== BillingPlan.CUSTOM} {/if} From b097c06656fe3dcab50ed6886e9963620449e065 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 16 Dec 2024 12:01:22 +0530 Subject: [PATCH 013/231] fix: simplify draft checks. --- .../message-[message]/emailMessage.svelte | 18 +++++++----------- .../message-[message]/updateTargets.svelte | 12 +++++++----- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/routes/(console)/project-[project]/messaging/message-[message]/emailMessage.svelte b/src/routes/(console)/project-[project]/messaging/message-[message]/emailMessage.svelte index 6fcaad6d47..36c479683b 100644 --- a/src/routes/(console)/project-[project]/messaging/message-[message]/emailMessage.svelte +++ b/src/routes/(console)/project-[project]/messaging/message-[message]/emailMessage.svelte @@ -60,25 +60,21 @@ subject === message.data.subject && content === message.data.content && html === ((message.data['html'] ?? false) as boolean); + + $: isDraft = message.status === 'draft';
    - +
    Message
    - - + + Enable the HTML mode if your message contains HTML tags. diff --git a/src/routes/(console)/project-[project]/messaging/message-[message]/updateTargets.svelte b/src/routes/(console)/project-[project]/messaging/message-[message]/updateTargets.svelte index 8c112fba95..c05bdce614 100644 --- a/src/routes/(console)/project-[project]/messaging/message-[message]/updateTargets.svelte +++ b/src/routes/(console)/project-[project]/messaging/message-[message]/updateTargets.svelte @@ -93,11 +93,13 @@ } } + $: isDraft = message.status === 'draft'; + $: disabled = symmetricDifference(targetIds, Object.keys(selectedTargetsById)).length === 0; - + Targets {@const sum = targetIds.length} @@ -106,7 +108,7 @@
    Target
    - {#if message.status == 'draft'} + {#if isDraft}
    - {:else if message.status == 'draft'} + {:else if isDraft} (showTargets = true)}>Add a target {:else} From 95865e3ccbeecdd19dc3aaa60ba927f403fd2697 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 16 Dec 2024 16:55:47 +0530 Subject: [PATCH 014/231] add: users section. --- .../messaging/message-[message]/+layout.ts | 10 +- .../messaging/message-[message]/+page.svelte | 2 + .../message-[message]/recipients.svelte | 91 +++++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/routes/(console)/project-[project]/messaging/message-[message]/recipients.svelte diff --git a/src/routes/(console)/project-[project]/messaging/message-[message]/+layout.ts b/src/routes/(console)/project-[project]/messaging/message-[message]/+layout.ts index 7e3985ea37..637631dd93 100644 --- a/src/routes/(console)/project-[project]/messaging/message-[message]/+layout.ts +++ b/src/routes/(console)/project-[project]/messaging/message-[message]/+layout.ts @@ -41,13 +41,21 @@ export const load: LayoutLoad = async ({ params, depends }) => { }) ); - await Promise.allSettled(usersPromise); + const messageRecipients: Record> = {}; + const messageRecipientsPromise = Object.values(message.users).map((userId) => + sdk.forProject.users.get(userId).then((user) => { + messageRecipients[user.$id] = user; + }) + ); + + await Promise.allSettled([usersPromise, messageRecipientsPromise]); return { message, topicsById, targetsById, usersById, + messageRecipients, header: Header, breadcrumbs: Breadcrumbs }; diff --git a/src/routes/(console)/project-[project]/messaging/message-[message]/+page.svelte b/src/routes/(console)/project-[project]/messaging/message-[message]/+page.svelte index 878c47ffdc..6e299cc847 100644 --- a/src/routes/(console)/project-[project]/messaging/message-[message]/+page.svelte +++ b/src/routes/(console)/project-[project]/messaging/message-[message]/+page.svelte @@ -12,6 +12,7 @@ import { MessagingProviderType } from '@appwrite.io/console'; import UpdateTopics from './updateTopics.svelte'; import UpdateTargets from './updateTargets.svelte'; + import Recipients from './recipients.svelte'; import { onMount } from 'svelte'; export let data: PageData; @@ -34,6 +35,7 @@ {/if} + {#if $message.status !== 'processing'} {/if} diff --git a/src/routes/(console)/project-[project]/messaging/message-[message]/recipients.svelte b/src/routes/(console)/project-[project]/messaging/message-[message]/recipients.svelte new file mode 100644 index 0000000000..fcce2439d3 --- /dev/null +++ b/src/routes/(console)/project-[project]/messaging/message-[message]/recipients.svelte @@ -0,0 +1,91 @@ + + + + Users + + {@const sum = messageRecipients.length} + {#if sum} +
    + + + Name + Identifier + + + {#each messageRecipients.slice(offset, offset + limit) as recipient (recipient.$id)} + + +
    + + {recipient.name} + +
    +
    + + + {getIdentifier(recipient)} + + +
    + {/each} +
    +
    +
    +

    Total users: {messageRecipients.length}

    + +
    +
    + {:else} + +
    + No users have been selected. +

    + Need a hand? Check out our + + . +

    +
    +
    + {/if} +
    +
    From bcbf5c75b5faa7ee1b82b3c0192949d586774809 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 19 Dec 2024 13:25:27 +0530 Subject: [PATCH 015/231] address comments. --- .../billing/estimatedTotalBox.svelte | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/lib/components/billing/estimatedTotalBox.svelte b/src/lib/components/billing/estimatedTotalBox.svelte index df06ef0b73..b73c87378c 100644 --- a/src/lib/components/billing/estimatedTotalBox.svelte +++ b/src/lib/components/billing/estimatedTotalBox.svelte @@ -34,17 +34,14 @@ : 0; $: extraSeatsCost = (collaborators?.length ?? 0) * (selectedPlan?.addons?.member?.price ?? 0); - $: grossCost = - isScaleUpgrade || isScaleDowngrade - ? selectedPlan.price + extraSeatsCost - unUsedBalances - : selectedPlan.price + extraSeatsCost; + $: grossCost = isScaleUpgrade + ? selectedPlan.price + extraSeatsCost - unUsedBalances + : selectedPlan.price + extraSeatsCost; $: estimatedTotal = couponData?.status === 'active' ? Math.max(0, grossCost - couponData.credits) : grossCost; $: trialEndDate = new Date( billingPayDate.getTime() + selectedPlan.trialDays * 24 * 60 * 60 * 1000 ); - - $: isRefund = isScaleDowngrade && grossCost < 0;

    -{formatCurrency(unUsedBalances)}

    - {:else if isScaleDowngrade} -
    - Unused {currentOrgPlan.name} plan balance -

    -{formatCurrency(currentOrgPlan.price)}

    -
    {/if} {#if couponData?.status === 'active'} @@ -107,15 +99,28 @@

    - You'll {isRefund ? 'receive a refund of' : 'pay'} - {formatCurrency(estimatedTotal)} - now, with our first billing cycle starting on - {!selectedPlan.trialDays - ? toLocaleDate(billingPayDate.toString()) - : toLocaleDate(trialEndDate.toString())}. Once your credits run out, you'll be charged - {formatCurrency(selectedPlan.price)} plus usage fees every 30 days. + {#if isScaleDowngrade} + You'll continue using the {currentOrgPlan.name} plan until your current cycle ends on + {!selectedPlan.trialDays + ? toLocaleDate(billingPayDate.toString()) + : toLocaleDate(trialEndDate.toString())}. Starting the next cycle, your plan will switch to {selectedPlan.name}, and you'll be + charged + {formatCurrency(grossCost)} + every 30 days. + {:else} + You'll pay + {formatCurrency(estimatedTotal)} + now, with our first billing cycle starting on + {!selectedPlan.trialDays + ? toLocaleDate(billingPayDate.toString()) + : toLocaleDate(trialEndDate.toString())}. Once your credits run out, you'll be charged + {formatCurrency(selectedPlan.price)} plus usage fees every 30 + days. + {/if}

    From b6a517a8cf952c9d3ba5d982a34e7c4f23935dff Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 19 Dec 2024 13:25:35 +0530 Subject: [PATCH 016/231] ran: formatter. --- src/lib/components/billing/planSelection.svelte | 6 +----- src/lib/sdk/billing.ts | 7 ++----- src/lib/stores/stripe.ts | 4 ++-- src/routes/(console)/account/organizations/+page.ts | 10 ++++------ src/routes/+layout.ts | 4 +++- 5 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/lib/components/billing/planSelection.svelte b/src/lib/components/billing/planSelection.svelte index cfcb28bbab..4a6e1f7caf 100644 --- a/src/lib/components/billing/planSelection.svelte +++ b/src/lib/components/billing/planSelection.svelte @@ -77,11 +77,7 @@
  • - +

    diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index bee94ffc3b..57ad227be1 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -318,14 +318,11 @@ export class Billing { ); } - async validateOrganization( - organizationId: string, - invites: string[], - ): Promise { + async validateOrganization(organizationId: string, invites: string[]): Promise { const path = `/organizations/${organizationId}/validate`; const params = { organizationId, - invites, + invites }; const uri = new URL(this.client.config.endpoint + path); return await this.client.call( diff --git a/src/lib/stores/stripe.ts b/src/lib/stores/stripe.ts index 3579746463..e62110d209 100644 --- a/src/lib/stores/stripe.ts +++ b/src/lib/stores/stripe.ts @@ -130,8 +130,8 @@ export async function confirmPayment( clientSecret: clientSecret, confirmParams: { return_url: url, - payment_method: paymentMethod.providerMethodId, - }, + payment_method: paymentMethod.providerMethodId + } }); if (error) { if (returnError) { diff --git a/src/routes/(console)/account/organizations/+page.ts b/src/routes/(console)/account/organizations/+page.ts index 803497c6a8..237a3772d7 100644 --- a/src/routes/(console)/account/organizations/+page.ts +++ b/src/routes/(console)/account/organizations/+page.ts @@ -10,13 +10,11 @@ export const load: PageLoad = async ({ url, route }) => { const limit = getLimit(url, route, CARD_LIMIT); const offset = pageToOffset(page, limit); - const queries = [ - Query.offset(offset), - Query.limit(limit), - Query.orderDesc('') - ]; + const queries = [Query.offset(offset), Query.limit(limit), Query.orderDesc('')]; - const organizations = isCloud ? await sdk.forConsole.billing.listOrganization(queries) : sdk.forConsole.teams.list(queries); + const organizations = isCloud + ? await sdk.forConsole.billing.listOrganization(queries) + : sdk.forConsole.teams.list(queries); return { offset, diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 6468cab571..4c9b760ca7 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -29,7 +29,9 @@ export const load: LayoutLoad = async ({ depends, url, route }) => { if (account) { return { account, - organizations: isCloud ? await sdk.forConsole.billing.listOrganization() : await sdk.forConsole.teams.list() + organizations: isCloud + ? await sdk.forConsole.billing.listOrganization() + : await sdk.forConsole.teams.list() }; } From 867320911c202c46e618cc904818a092b0a3c141 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 22 Dec 2024 13:14:06 +0545 Subject: [PATCH 017/231] update models --- src/lib/sdk/billing.ts | 24 ++++++++++++++++++------ src/lib/stores/organization.ts | 2 ++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index bee94ffc3b..01e2008a5f 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -174,6 +174,10 @@ export type Aggregation = { * Usage logs for the billing period. */ resources: OrganizationUsage; + /** + * Aggregation billing plan + */ + plan: string; }; export type OrganizationUsage = { @@ -388,19 +392,27 @@ export class Billing { ); } - async getPlan(organizationId: string): Promise { + async getOrganizationPlan(organizationId: string): Promise { const path = `/organizations/${organizationId}/plan`; - const params = { - organizationId - }; const uri = new URL(this.client.config.endpoint + path); return await this.client.call( 'get', uri, { 'content-type': 'application/json' - }, - params + } + ); + } + + async getPlan(planId: string): Promise { + const path = `/console/plans/${planId}`; + const uri = new URL(this.client.config.endpoint + path); + return await this.client.call( + 'get', + uri, + { + 'content-type': 'application/json' + } ); } diff --git a/src/lib/stores/organization.ts b/src/lib/stores/organization.ts index 0e1912c5fc..53420f4e50 100644 --- a/src/lib/stores/organization.ts +++ b/src/lib/stores/organization.ts @@ -29,6 +29,8 @@ export type Organization = Models.Team> & { amount: number; billingTaxId?: string; billingPlanDowngrade?: Tier; + billingAggregationId: string; + billingInvoiceId: string; }; export type OrganizationList = { From 8fdf7c515f5f8470f17723cc7922c5adabf05702 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 22 Dec 2024 13:15:42 +0545 Subject: [PATCH 018/231] refactor and get current plan from aggregation --- .../billing/+page.svelte | 3 ++- .../billing/+page.ts | 25 ++++++++++++++----- .../billing/planSummary.svelte | 5 ++-- .../change-plan/+page.svelte | 2 +- .../usage/[[invoice]]/+page.ts | 2 +- .../storage/bucket-[bucket]/settings/+page.ts | 2 +- 6 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/billing/+page.svelte b/src/routes/(console)/organization-[organization]/billing/+page.svelte index d3d6b7fd1a..ad680d21a2 100644 --- a/src/routes/(console)/organization-[organization]/billing/+page.svelte +++ b/src/routes/(console)/organization-[organization]/billing/+page.svelte @@ -123,7 +123,8 @@ diff --git a/src/routes/(console)/organization-[organization]/billing/+page.ts b/src/routes/(console)/organization-[organization]/billing/+page.ts index 0e945f906a..14957a4d3a 100644 --- a/src/routes/(console)/organization-[organization]/billing/+page.ts +++ b/src/routes/(console)/organization-[organization]/billing/+page.ts @@ -21,10 +21,16 @@ export const load: PageLoad = async ({ parent, depends }) => { const billingAddressId = (organization as Organization)?.billingAddressId; const billingAddressPromise: Promise
    = billingAddressId ? sdk.forConsole.billing - .getOrganizationBillingAddress(organization.$id, billingAddressId) - .catch(() => null) + .getOrganizationBillingAddress(organization.$id, billingAddressId) + .catch(() => null) : null; + const billingAggregationId = (organization as Organization)?.billingAggregationId; + const billingInvoiceId = (organization as Organization)?.billingInvoiceId; + + const billingAggregation = await sdk.forConsole.billing.getAggregation(organization.$id, billingAggregationId); + console.log(billingAggregation); + const [ paymentMethods, addressList, @@ -32,18 +38,22 @@ export const load: PageLoad = async ({ parent, depends }) => { billingAddress, currentPlan, creditList, - invoices + invoices, + aggregationBillingPlan, + billingInvoice, ] = await Promise.all([ sdk.forConsole.billing.listPaymentMethods(), sdk.forConsole.billing.listAddresses(), sdk.forConsole.billing.listAggregation(organization.$id), billingAddressPromise, - sdk.forConsole.billing.getPlan(organization.$id), + sdk.forConsole.billing.getOrganizationPlan(organization.$id), sdk.forConsole.billing.listCredits(organization.$id), sdk.forConsole.billing.listInvoices(organization.$id, [ Query.limit(1), Query.equal('from', organization.billingCurrentInvoiceDate) - ]) + ]), + sdk.forConsole.billing.getPlan(billingAggregation.plan), + sdk.forConsole.billing.getInvoice(organization.$id, billingInvoiceId) ]); return { @@ -52,7 +62,10 @@ export const load: PageLoad = async ({ parent, depends }) => { aggregationList, billingAddress, currentPlan, + aggregationBillingPlan, creditList, - invoices + invoices, + billingAggregation, + billingInvoice }; }; diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte index c84356b753..f1c6c64650 100644 --- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte +++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte @@ -17,8 +17,9 @@ export let members: Models.MembershipList; export let currentPlan: Plan; export let creditList: CreditList; + export let currentInvoice: Invoice | undefined = undefined - const currentInvoice: Invoice | undefined = invoices.length > 0 ? invoices[0] : undefined; + // const currentInvoice: Invoice | undefined = invoices.length > 0 ? invoices[0] : undefined; const extraMembers = members.total > 1 ? members.total - 1 : 0; const availableCredit = creditList.available; const today = new Date(); @@ -45,7 +46,7 @@ - {tierToPlan($organization?.billingPlan)?.name} plan + {currentPlan.name} plan
    {isTrial || $organization?.billingPlan === BillingPlan.GITHUB_EDUCATION ? formatCurrency(0) diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index fe317b18a4..a44ab8ff08 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -107,7 +107,7 @@ billingPlan = BillingPlan.PRO; } - const currentPlan = await sdk.forConsole.billing.getPlan($organization?.$id); + const currentPlan = await sdk.forConsole.billing.getOrganizationPlan($organization?.$id); selfService = currentPlan.selfService; }); diff --git a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.ts b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.ts index 9ffafbac21..b3546b01de 100644 --- a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.ts +++ b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.ts @@ -45,7 +45,7 @@ export const load: PageLoad = async ({ params, parent }) => { sdk.forConsole.billing.listInvoices(org.$id, [Query.orderDesc('from')]), sdk.forConsole.billing.listUsage(params.organization, startDate, endDate), sdk.forConsole.teams.listMemberships(params.organization), - sdk.forConsole.billing.getPlan(org.$id) + sdk.forConsole.billing.getOrganizationPlan(org.$id) ]); const projectNames: { [key: string]: Models.Project } = {}; diff --git a/src/routes/(console)/project-[project]/storage/bucket-[bucket]/settings/+page.ts b/src/routes/(console)/project-[project]/storage/bucket-[bucket]/settings/+page.ts index 546bfa7a8a..83972d5a6a 100644 --- a/src/routes/(console)/project-[project]/storage/bucket-[bucket]/settings/+page.ts +++ b/src/routes/(console)/project-[project]/storage/bucket-[bucket]/settings/+page.ts @@ -3,7 +3,7 @@ import { sdk } from '$lib/stores/sdk'; export const load: PageLoad = async ({ parent }) => { const { organization } = await parent(); - const currentPlan = await sdk.forConsole.billing.getPlan(organization.$id); + const currentPlan = await sdk.forConsole.billing.getOrganizationPlan(organization.$id); return { currentPlan }; From 1ee29b20777877ed6472b1aded55122168e716f8 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 22 Dec 2024 13:55:58 +0545 Subject: [PATCH 019/231] update summary --- .../organization-[organization]/billing/planSummary.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte index f1c6c64650..2ef69316b7 100644 --- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte +++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte @@ -39,7 +39,7 @@

    - Billing period: {toLocaleDate($organization?.billingCurrentInvoiceDate)} - {toLocaleDate( + Due at: {toLocaleDate( $organization?.billingNextInvoiceDate )}

    From 16705d38aac193517c7de52b730acd12e17f040a Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 23 Dec 2024 07:11:16 +0545 Subject: [PATCH 020/231] fix rename --- src/routes/(console)/organization-[organization]/+layout.ts | 2 +- src/routes/(console)/project-[project]/+layout.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/+layout.ts b/src/routes/(console)/organization-[organization]/+layout.ts index 650990e866..cd1968ea8e 100644 --- a/src/routes/(console)/organization-[organization]/+layout.ts +++ b/src/routes/(console)/organization-[organization]/+layout.ts @@ -27,7 +27,7 @@ export const load: LayoutLoad = async ({ params, depends }) => { const res = await sdk.forConsole.billing.getRoles(params.organization); roles = res.roles; scopes = res.scopes; - currentPlan = await sdk.forConsole.billing.getPlan(params.organization); + currentPlan = await sdk.forConsole.billing.getOrganizationPlan(params.organization); if (scopes.includes('billing.read')) { await failedInvoice.load(params.organization); if (get(failedInvoice)) { diff --git a/src/routes/(console)/project-[project]/+layout.ts b/src/routes/(console)/project-[project]/+layout.ts index 018462d75a..8725851436 100644 --- a/src/routes/(console)/project-[project]/+layout.ts +++ b/src/routes/(console)/project-[project]/+layout.ts @@ -29,7 +29,7 @@ export const load: LayoutLoad = async ({ params, depends }) => { let roles = isCloud ? [] : defaultRoles; let scopes = isCloud ? [] : defaultScopes; if (isCloud) { - currentPlan = await sdk.forConsole.billing.getPlan(project.teamId); + currentPlan = await sdk.forConsole.billing.getOrganizationPlan(project.teamId); const res = await sdk.forConsole.billing.getRoles(project.teamId); roles = res.roles; scopes = res.scopes; From 14a0cacbf68c0e41ec36ef82e32c2ef90489d370 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 23 Dec 2024 08:17:14 +0545 Subject: [PATCH 021/231] refactor --- .../organization-[organization]/billing/+page.svelte | 3 +-- .../(console)/organization-[organization]/billing/+page.ts | 6 ------ .../organization-[organization]/billing/planSummary.svelte | 3 +-- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/billing/+page.svelte b/src/routes/(console)/organization-[organization]/billing/+page.svelte index ad680d21a2..bf09c55759 100644 --- a/src/routes/(console)/organization-[organization]/billing/+page.svelte +++ b/src/routes/(console)/organization-[organization]/billing/+page.svelte @@ -124,8 +124,7 @@ creditList={data?.creditList} members={data?.members} currentPlan={data?.aggregationBillingPlan} - currentInvoice={data?.billingInvoice} - invoices={data?.invoices.invoices} /> + currentInvoice={data?.billingInvoice} /> diff --git a/src/routes/(console)/organization-[organization]/billing/+page.ts b/src/routes/(console)/organization-[organization]/billing/+page.ts index c98183028b..25c390c2a4 100644 --- a/src/routes/(console)/organization-[organization]/billing/+page.ts +++ b/src/routes/(console)/organization-[organization]/billing/+page.ts @@ -36,7 +36,6 @@ export const load: PageLoad = async ({ parent, depends }) => { aggregationList, billingAddress, creditList, - invoices, aggregationBillingPlan, billingInvoice, ] = await Promise.all([ @@ -45,10 +44,6 @@ export const load: PageLoad = async ({ parent, depends }) => { sdk.forConsole.billing.listAggregation(organization.$id), billingAddressPromise, sdk.forConsole.billing.listCredits(organization.$id), - sdk.forConsole.billing.listInvoices(organization.$id, [ - Query.limit(1), - Query.equal('from', organization.billingCurrentInvoiceDate) - ]), sdk.forConsole.billing.getPlan(billingAggregation.plan), sdk.forConsole.billing.getInvoice(organization.$id, billingInvoiceId) ]); @@ -60,7 +55,6 @@ export const load: PageLoad = async ({ parent, depends }) => { billingAddress, aggregationBillingPlan, creditList, - invoices, billingAggregation, billingInvoice }; diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte index 2ef69316b7..eeaee9aba5 100644 --- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte +++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte @@ -3,7 +3,7 @@ import { CardGrid, Collapsible, CollapsibleItem, Heading } from '$lib/components'; import { Button } from '$lib/elements/forms'; import { toLocaleDate } from '$lib/helpers/date'; - import { plansInfo, tierToPlan, upgradeURL } from '$lib/stores/billing'; + import { plansInfo, upgradeURL } from '$lib/stores/billing'; import { organization } from '$lib/stores/organization'; import type { CreditList, Invoice, Plan } from '$lib/sdk/billing'; import { abbreviateNumber, formatCurrency, formatNumberWithCommas } from '$lib/helpers/numbers'; @@ -13,7 +13,6 @@ import { tooltip } from '$lib/actions/tooltip'; import { type Models } from '@appwrite.io/console'; - export let invoices: Array; export let members: Models.MembershipList; export let currentPlan: Plan; export let creditList: CreditList; From 9f517bd0681a462a6d23c3dacd7011ac8e1be843 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 23 Dec 2024 08:38:16 +0545 Subject: [PATCH 022/231] improvements on error --- .../billing/+page.ts | 21 ++++++++++++------- .../billing/planSummary.svelte | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/billing/+page.ts b/src/routes/(console)/organization-[organization]/billing/+page.ts index 25c390c2a4..12db3b5479 100644 --- a/src/routes/(console)/organization-[organization]/billing/+page.ts +++ b/src/routes/(console)/organization-[organization]/billing/+page.ts @@ -4,7 +4,6 @@ import type { Organization } from '$lib/stores/organization'; import { sdk } from '$lib/stores/sdk'; import { redirect } from '@sveltejs/kit'; import type { PageLoad } from './$types'; -import { Query } from '@appwrite.io/console'; export const load: PageLoad = async ({ parent, depends }) => { const { organization, scopes } = await parent(); @@ -26,32 +25,40 @@ export const load: PageLoad = async ({ parent, depends }) => { : null; const billingAggregationId = (organization as Organization)?.billingAggregationId; + + let billingAggregation = null; + try { + billingAggregation = await sdk.forConsole.billing.getAggregation(organization.$id, billingAggregationId); + } catch (e) { + // ignore error + } + const billingInvoiceId = (organization as Organization)?.billingInvoiceId; + let billingInvoice = null; + try { + billingInvoice = await sdk.forConsole.billing.getInvoice(organization.$id, billingInvoiceId) + } catch (e) { + // ignore error + } - const billingAggregation = await sdk.forConsole.billing.getAggregation(organization.$id, billingAggregationId); const [ paymentMethods, addressList, - aggregationList, billingAddress, creditList, aggregationBillingPlan, - billingInvoice, ] = await Promise.all([ sdk.forConsole.billing.listPaymentMethods(), sdk.forConsole.billing.listAddresses(), - sdk.forConsole.billing.listAggregation(organization.$id), billingAddressPromise, sdk.forConsole.billing.listCredits(organization.$id), sdk.forConsole.billing.getPlan(billingAggregation.plan), - sdk.forConsole.billing.getInvoice(organization.$id, billingInvoiceId) ]); return { paymentMethods, addressList, - aggregationList, billingAddress, aggregationBillingPlan, creditList, diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte index eeaee9aba5..d642ae1087 100644 --- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte +++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte @@ -54,7 +54,7 @@ : ''}
    - {#if $organization?.billingPlan !== BillingPlan.FREE && $organization?.billingPlan !== BillingPlan.GITHUB_EDUCATION && extraUsage > 0} + {#if currentPlan.budgeting && extraUsage > 0} Add-ons Date: Tue, 24 Dec 2024 07:09:19 +0545 Subject: [PATCH 023/231] credit support from plan --- src/lib/sdk/billing.ts | 1 + .../organization-[organization]/billing/planSummary.svelte | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index ef581a0eb7..711be9befd 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -291,6 +291,7 @@ export type Plan = { backupsEnabled: boolean; backupPolicies: number; emailBranding: boolean; + supportsCredit: boolean; }; export type PlansInfo = { diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte index 3d05ac3a61..d71c709d87 100644 --- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte +++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte @@ -132,7 +132,7 @@ {/if} - {#if $organization?.billingPlan !== BillingPlan.FREE && availableCredit > 0} + {#if currentPlan.supportsCredit && availableCredit > 0}

    - Due at: {toLocaleDate( - $organization?.billingNextInvoiceDate - )} + Due at: {toLocaleDate($organization?.billingNextInvoiceDate)}

    - - {currentPlan.name} plan + {currentPlan.name} plan
    {isTrial || $organization?.billingPlan === BillingPlan.GITHUB_EDUCATION ? formatCurrency(0) @@ -204,17 +213,21 @@
    {:else}
    - + {#if $organization?.billingPlanDowngrade !== null} + + {:else} + + {/if} diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index 2158fdeb12..8e1a777c92 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -155,6 +155,8 @@ }) }); + await invalidate(Dependencies.ORGANIZATION); + await goto(previousPage); addNotification({ type: 'success', From fb926d9d6fb4e02b3506bce632ef6a5be7d12e7b Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 24 Dec 2024 08:02:47 +0545 Subject: [PATCH 025/231] cancel downgrade --- .../billing/cancelDowngradeModel.svelte | 51 +++++++++++++++++++ .../billing/planSummary.svelte | 21 +++----- .../settings/deleteOrganizationModal.svelte | 2 +- 3 files changed, 58 insertions(+), 16 deletions(-) create mode 100644 src/routes/(console)/organization-[organization]/billing/cancelDowngradeModel.svelte diff --git a/src/routes/(console)/organization-[organization]/billing/cancelDowngradeModel.svelte b/src/routes/(console)/organization-[organization]/billing/cancelDowngradeModel.svelte new file mode 100644 index 0000000000..78785305b1 --- /dev/null +++ b/src/routes/(console)/organization-[organization]/billing/cancelDowngradeModel.svelte @@ -0,0 +1,51 @@ + + +
    + +

    + Your organization is set to change to + {tierToPlan($organization?.billingPlanDowngrade).name} + plan on {toLocaleDate($organization.billingNextInvoiceDate)}. +

    +

    Are you sure you want to cancel the change?

    + + + + +
    +
    diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte index d9b9ddc08d..09cc3754e5 100644 --- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte +++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte @@ -8,18 +8,19 @@ import type { CreditList, Invoice, Plan } from '$lib/sdk/billing'; import { abbreviateNumber, formatCurrency, formatNumberWithCommas } from '$lib/helpers/numbers'; import { humanFileSize } from '$lib/helpers/sizeConvertion'; - import { BillingPlan, Dependencies } from '$lib/constants'; + import { BillingPlan } from '$lib/constants'; import { trackEvent } from '$lib/actions/analytics'; import { tooltip } from '$lib/actions/tooltip'; import { type Models } from '@appwrite.io/console'; - import { sdk } from '$lib/stores/sdk'; - import { invalidate } from '$app/navigation'; + import CancelDowngradeModel from './cancelDowngradeModel.svelte'; export let members: Models.MembershipList; export let currentPlan: Plan; export let creditList: CreditList; export let currentInvoice: Invoice | undefined = undefined; + let showCancel: boolean = false; + const extraMembers = members.total > 1 ? members.total - 1 : 0; const availableCredit = creditList.available; const today = new Date(); @@ -28,17 +29,6 @@ $plansInfo.get($organization.billingPlan)?.trialDays; const extraUsage = currentInvoice ? currentInvoice.amount - currentPlan?.price : 0; const extraAddons = currentInvoice ? currentInvoice.usage?.length : 0; - - const cancelDowngrade = async () => { - await sdk.forConsole.billing.cancelDowngrade( - $organization.$id - ); - await invalidate(Dependencies.ORGANIZATION); - trackEvent('click_organization_plan_update', { - from: 'button', - source: 'billing_tab' - }); - }; {#if $organization} @@ -214,7 +204,7 @@ {:else}
    {#if $organization?.billingPlanDowngrade !== null} - + {:else}
    diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index 8e1a777c92..e1072e2478 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -321,7 +321,7 @@ you will be charged {formatCurrency( extraMembers * - ($plansInfo?.get(billingPlan)?.addons?.member?.price ?? 0) + ($plansInfo?.get(billingPlan)?.usage?.member?.price ?? 0) )} monthly for {extraMembers} team members. This will be reflected in your next invoice. diff --git a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/totalMembers.svelte b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/totalMembers.svelte index d63585b52d..b92803eaef 100644 --- a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/totalMembers.svelte +++ b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/totalMembers.svelte @@ -46,7 +46,7 @@

    From 34f0727d5fc3689fb75c19dcf45113487c41fc35 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 9 Jan 2025 11:48:59 +0530 Subject: [PATCH 027/231] ci: empty commit From 5d84c3b52c8dfcb8640565dbde614fa1256483ae Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 12 Jan 2025 07:28:45 +0000 Subject: [PATCH 028/231] fix types --- .../components/billing/estimatedTotal.svelte | 16 ++++ src/lib/sdk/billing.ts | 80 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/lib/components/billing/estimatedTotal.svelte diff --git a/src/lib/components/billing/estimatedTotal.svelte b/src/lib/components/billing/estimatedTotal.svelte new file mode 100644 index 0000000000..40cac8a00a --- /dev/null +++ b/src/lib/components/billing/estimatedTotal.svelte @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index 85673c6156..04cbbaef6f 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -65,6 +65,28 @@ export type InvoiceList = { total: number; }; +export type Estimation = { + amount: number; + grossAmount: number; + credits: number; + discount: number; + items: EstimationItem[]; +} + +export type EstimationItem = { + label: string; + value: number; +} + +export type EstimationDeleteOrganization = { + amount: number; + grossAmount: number; + credits: number; + discount: number; + items: EstimationItem[], + unpaidInvoices: Invoice[]; +} + export type Coupon = { $id: string; code: string; @@ -396,6 +418,28 @@ export class Billing { ); } + async estimationCreateOrganization( + billingPlan: string, + couponId: string = null, + invites: Array = [], + ): Promise { + const path = `/organizations`; + const params = { + billingPlan, + couponId, + invites, + }; + const uri = new URL(this.client.config.endpoint + path); + return await this.client.call( + 'POST', + uri, + { + 'content-type': 'application/json' + }, + params + ); + } + async deleteOrganization(organizationId: string): Promise { const path = `/organizations/${organizationId}`; const params = { @@ -412,6 +456,18 @@ export class Billing { ); } + async estimationDeleteOrganization(organizationId: string): Promise { + const path = `/organizations/${organizationId}/predictions/delete-organization`; + const uri = new URL(this.client.config.endpoint + path); + return await this.client.call( + 'patch', + uri, + { + 'content-type': 'application/json' + } + ); + } + async getOrganizationPlan(organizationId: string): Promise { const path = `/organizations/${organizationId}/plan`; const uri = new URL(this.client.config.endpoint + path); @@ -475,6 +531,30 @@ export class Billing { params ); } + + async estimationUpdatePlan( + organizationId: string, + billingPlan: string, + couponId: string = null, + invites: Array = [], + ): Promise { + const path = `/organizations/${organizationId}/predictions/update-plan`; + const params = { + billingPlan, + couponId, + invites, + }; + const uri = new URL(this.client.config.endpoint + path); + return await this.client.call( + 'patch', + uri, + { + 'content-type': 'application/json' + }, + params + ); + } + async cancelDowngrade( organizationId: string ): Promise { From 31b1467a98ab23500f30063582bf1a91744fcb76 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 14 Jan 2025 08:05:18 +0000 Subject: [PATCH 029/231] use new estimation api for update plan and create organiation --- .../billing/discountsApplied.svelte | 21 +++++ .../components/billing/estimatedTotal.svelte | 93 +++++++++++++++++-- src/lib/sdk/billing.ts | 11 ++- .../create-organization/+page.svelte | 12 +++ .../change-plan/+page.svelte | 16 +++- 5 files changed, 141 insertions(+), 12 deletions(-) create mode 100644 src/lib/components/billing/discountsApplied.svelte diff --git a/src/lib/components/billing/discountsApplied.svelte b/src/lib/components/billing/discountsApplied.svelte new file mode 100644 index 0000000000..0a815a88cc --- /dev/null +++ b/src/lib/components/billing/discountsApplied.svelte @@ -0,0 +1,21 @@ + + +{#if value > 0} + +
    +

    +

    +
    + -{formatCurrency(value)} +
    +{/if} diff --git a/src/lib/components/billing/estimatedTotal.svelte b/src/lib/components/billing/estimatedTotal.svelte index 40cac8a00a..f39f94f96e 100644 --- a/src/lib/components/billing/estimatedTotal.svelte +++ b/src/lib/components/billing/estimatedTotal.svelte @@ -1,16 +1,97 @@ + +{#if estimation} + +
    + + {#each estimation.items ?? [] as item} + +

    {item.label}

    +

    {formatCurrency(item.value)}

    +
    + {/each} + {#each estimation.discounts ?? [] as item} + + {/each} +
    + +

    + Total due
    +

    +

    + {formatCurrency(estimation.grossAmount)} +

    +
    + + - \ No newline at end of file + +
    +{/if} \ No newline at end of file diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index 7305e8abe1..f4734d500a 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -71,6 +71,9 @@ export type Estimation = { credits: number; discount: number; items: EstimationItem[]; + discounts: EstimationItem[]; + trialDays: number; + trialEndDate: string | undefined; } export type EstimationItem = { @@ -420,7 +423,7 @@ export class Billing { couponId: string = null, invites: Array = [], ): Promise { - const path = `/organizations`; + const path = `/organizations/estimations/create-organization`; const params = { billingPlan, couponId, @@ -428,7 +431,7 @@ export class Billing { }; const uri = new URL(this.client.config.endpoint + path); return await this.client.call( - 'POST', + 'patch', uri, { 'content-type': 'application/json' @@ -454,7 +457,7 @@ export class Billing { } async estimationDeleteOrganization(organizationId: string): Promise { - const path = `/organizations/${organizationId}/predictions/delete-organization`; + const path = `/organizations/${organizationId}/estimations/delete-organization`; const uri = new URL(this.client.config.endpoint + path); return await this.client.call( 'patch', @@ -535,7 +538,7 @@ export class Billing { couponId: string = null, invites: Array = [], ): Promise { - const path = `/organizations/${organizationId}/predictions/update-plan`; + const path = `/organizations/${organizationId}/estimations/update-plan`; const params = { billingPlan, couponId, diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte index 05da83c37f..59e84076cf 100644 --- a/src/routes/(console)/create-organization/+page.svelte +++ b/src/routes/(console)/create-organization/+page.svelte @@ -9,6 +9,7 @@ PlanSelection, SelectPaymentMethod } from '$lib/components/billing'; + import EstimatedTotal from '$lib/components/billing/estimatedTotal.svelte'; import ValidateCreditModal from '$lib/components/billing/validateCreditModal.svelte'; import Default from '$lib/components/roles/default.svelte'; import { BillingPlan, Dependencies } from '$lib/constants'; @@ -51,6 +52,7 @@ let billingPlan: BillingPlan = BillingPlan.FREE; let paymentMethodId: string; let collaborators: string[] = []; + let couponId: string | undefined; let couponData: Partial = { code: null, status: null, @@ -233,6 +235,11 @@ id="members" /> + {#if !couponData?.code}

    - -{formatCurrency(value)} + {#if value >= 100} +

    Credits applied

    + {:else} + -{formatCurrency(value)} + {/if} {/if} diff --git a/src/routes/(console)/apply-credit/+page.svelte b/src/routes/(console)/apply-credit/+page.svelte index 884fd1763e..74d003861f 100644 --- a/src/routes/(console)/apply-credit/+page.svelte +++ b/src/routes/(console)/apply-credit/+page.svelte @@ -8,6 +8,7 @@ EstimatedTotalBox, SelectPaymentMethod } from '$lib/components/billing'; + import EstimatedTotal from '$lib/components/billing/estimatedTotal.svelte'; import { BillingPlan, Dependencies } from '$lib/constants'; import { Button, Form, FormList, InputSelect, InputTags, InputText } from '$lib/elements/forms'; import { toLocaleDate } from '$lib/helpers/date'; @@ -285,12 +286,11 @@
  • {:else if selectedOrgId}
    - + couponId={couponData.code}> {#if campaign?.template === 'review' && (campaign?.cta || campaign?.claimed || campaign?.unclaimed)}

    {campaign?.cta}

    @@ -303,7 +303,7 @@

    {/if} -
    +
    {/if} From 293eac04ff0a9bfa15228560d92f5d7e88c56edd Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 15 Jan 2025 06:50:01 +0000 Subject: [PATCH 031/231] refactor plan selection --- src/lib/components/billing/index.ts | 2 + src/lib/components/billing/selectPlan.svelte | 52 +++++++++++++++++++ src/lib/sdk/billing.ts | 6 ++- .../create-organization/+page.svelte | 8 +-- .../change-plan/+page.svelte | 22 +++----- 5 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 src/lib/components/billing/selectPlan.svelte diff --git a/src/lib/components/billing/index.ts b/src/lib/components/billing/index.ts index 266d217d8a..0643e5922d 100644 --- a/src/lib/components/billing/index.ts +++ b/src/lib/components/billing/index.ts @@ -7,3 +7,5 @@ export { default as PlanComparisonBox } from './planComparisonBox.svelte'; export { default as EmptyCardCloud } from './emptyCardCloud.svelte'; export { default as CreditsApplied } from './creditsApplied.svelte'; export { default as PlanSelection } from './planSelection.svelte'; +export { default as EstimatedTotal } from './estimatedTotal.svelte'; +export { default as SelectPlan } from './selectPlan.svelte'; \ No newline at end of file diff --git a/src/lib/components/billing/selectPlan.svelte b/src/lib/components/billing/selectPlan.svelte new file mode 100644 index 0000000000..ecff50f99f --- /dev/null +++ b/src/lib/components/billing/selectPlan.svelte @@ -0,0 +1,52 @@ + + +{#if billingPlan} +
      + {#each $plansInfo.values() as plan} +
    • + + +
      +

      + {plan.name} + {#if $organization?.billingPlan === plan.$id && !isNewOrg} + Current plan + {/if} +

      +

      + {plan.desc} +

      +

      + {formatCurrency(plan?.price ?? 0)} +

      +
      +
      +
      +
    • + {/each} +
    +{/if} diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index f4734d500a..2245053c66 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -296,7 +296,9 @@ export type PlanAddon = { export type Plan = { $id: string; name: string; + desc: string; price: number; + order: number; bandwidth: number; storage: number; webhooks: number; @@ -332,7 +334,7 @@ export type Plan = { supportsCredit: boolean; }; -export type PlansInfo = { +export type PlanList = { plans: Plan[]; total: number; }; @@ -1262,7 +1264,7 @@ export class Billing { ); } - async getPlansInfo(): Promise { + async getPlansInfo(): Promise { const path = `/console/plans`; const params = {}; const uri = new URL(this.client.config.endpoint + path); diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte index 59e84076cf..3b758b0d39 100644 --- a/src/routes/(console)/create-organization/+page.svelte +++ b/src/routes/(console)/create-organization/+page.svelte @@ -6,8 +6,10 @@ import { EstimatedTotalBox, PlanComparisonBox, - PlanSelection, - SelectPaymentMethod + SelectPaymentMethod, + + SelectPlan + } from '$lib/components/billing'; import EstimatedTotal from '$lib/components/billing/estimatedTotal.svelte'; import ValidateCreditModal from '$lib/components/billing/validateCreditModal.svelte'; @@ -222,7 +224,7 @@ For more details on our plans, visit our .

    - + {#if billingPlan !== BillingPlan.FREE} $organization.billingPlan; - $: isDowngrade = billingPlan < $organization.billingPlan; + $: isUpgrade = $plansInfo.get(billingPlan).order > $currentPlan.order; + $: isDowngrade = $plansInfo.get(billingPlan).order < $currentPlan.order; $: if (billingPlan !== BillingPlan.FREE) { loadPaymentMethods(); } @@ -300,9 +299,8 @@ >Your contract is not eligible for manual changes. Please reach out to schedule a call or setup a dialog. {/if} - - {#if billingPlan !== BillingPlan.FREE && $organization.billingPlan !== billingPlan && $organization.billingPlan !== BillingPlan.CUSTOM} + {#if billingPlan !== BillingPlan.FREE && $organization.billingPlan !== billingPlan && $organization.billingPlan !== BillingPlan.CUSTOM && isUpgrade} - + {couponId} /> {:else if $organization.billingPlan !== BillingPlan.CUSTOM} {/if} From c5676817c3cfc63e2f8f001576aed2fb32bb1715 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 15 Jan 2025 07:31:04 +0000 Subject: [PATCH 032/231] fix after sync --- src/lib/components/billing/estimatedTotalBox.svelte | 10 +++++----- src/lib/components/billing/selectPlan.svelte | 1 - src/routes/(console)/apply-credit/+page.svelte | 7 +------ src/routes/+layout.ts | 1 - 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/lib/components/billing/estimatedTotalBox.svelte b/src/lib/components/billing/estimatedTotalBox.svelte index 581e261b5f..4d96f87c4d 100644 --- a/src/lib/components/billing/estimatedTotalBox.svelte +++ b/src/lib/components/billing/estimatedTotalBox.svelte @@ -28,12 +28,12 @@ $: currentOrgPlan = $plansInfo.get(currentTier); $: unUsedBalances = isScaleUpgrade ? currentOrgPlan.price + - (collaborators?.length ?? 0) * (currentOrgPlan?.addons?.member?.price ?? 0) + (collaborators?.length ?? 0) * (currentOrgPlan?.addons?.seats?.price ?? 0) : isScaleDowngrade ? currentOrgPlan.price : 0; - $: extraSeatsCost = (collaborators?.length ?? 0) * (selectedPlan?.addons?.member?.price ?? 0); + $: extraSeatsCost = (collaborators?.length ?? 0) * (selectedPlan?.addons?.seats?.price ?? 0); $: grossCost = isScaleUpgrade ? selectedPlan.price + extraSeatsCost - unUsedBalances : selectedPlan.price + extraSeatsCost; @@ -59,7 +59,7 @@

    {formatCurrency( isScaleDowngrade - ? (collaborators?.length ?? 0) * (selectedPlan?.addons?.member?.price ?? 0) + ? (collaborators?.length ?? 0) * (selectedPlan?.addons?.seats?.price ?? 0) : extraSeatsCost )}

    @@ -102,11 +102,11 @@ You'll pay {formatCurrency(estimatedTotal)} now, with your first billing cycle starting on {!currentPlan.trialDays + >{!currentOrgPlan.trialDays ? toLocaleDate(billingPayDate.toString()) : toLocaleDate(trialEndDate.toString())}. Once your credits run out, you'll be charged - {formatCurrency(currentPlan.price)} plus usage fees every 30 days. + {formatCurrency(currentOrgPlan.price)} plus usage fees every 30 days.

    diff --git a/src/lib/components/billing/selectPlan.svelte b/src/lib/components/billing/selectPlan.svelte index ecff50f99f..4447c17e3f 100644 --- a/src/lib/components/billing/selectPlan.svelte +++ b/src/lib/components/billing/selectPlan.svelte @@ -8,7 +8,6 @@ export let billingPlan: string; export let anyOrgFree = false; export let isNewOrg = false; - export let selfService = true; let classes: string = ''; export { classes as class }; diff --git a/src/routes/(console)/apply-credit/+page.svelte b/src/routes/(console)/apply-credit/+page.svelte index 502ede7ade..a33884a41d 100644 --- a/src/routes/(console)/apply-credit/+page.svelte +++ b/src/routes/(console)/apply-credit/+page.svelte @@ -3,12 +3,7 @@ import { base } from '$app/paths'; import { page } from '$app/stores'; import { Submit, trackError, trackEvent } from '$lib/actions/analytics'; - import { - CreditsApplied, - EstimatedTotalBox, - SelectPaymentMethod - } from '$lib/components/billing'; - import EstimatedTotal from '$lib/components/billing/estimatedTotal.svelte'; + import { CreditsApplied, EstimatedTotal, SelectPaymentMethod } from '$lib/components/billing'; import { BillingPlan, Dependencies } from '$lib/constants'; import { Button, Form, FormList, InputSelect, InputTags, InputText } from '$lib/elements/forms'; import { toLocaleDate } from '$lib/helpers/date'; diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index eb96a29c26..8161662735 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -6,7 +6,6 @@ import { redirect } from '@sveltejs/kit'; import { Dependencies } from '$lib/constants'; import type { LayoutLoad } from './$types'; import { redirectTo } from './store'; -import { isCloud } from '$lib/system'; import { base } from '$app/paths'; import type { Account } from '$lib/stores/user'; import type { AppwriteException } from '@appwrite.io/console'; From 8c9c413e4f0f4611c2730657adbdf490c7db8e09 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 15 Jan 2025 07:54:29 +0000 Subject: [PATCH 033/231] fix coupon --- .../create-organization/+page.svelte | 14 ---------- .../change-plan/+page.svelte | 27 +++++-------------- 2 files changed, 7 insertions(+), 34 deletions(-) diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte index 50ba69eff1..03ffc63d79 100644 --- a/src/routes/(console)/create-organization/+page.svelte +++ b/src/routes/(console)/create-organization/+page.svelte @@ -247,15 +247,6 @@ placeholder="Enter coupon code" id="couponId" /> - {#if !couponData?.code} - - {/if} {/if} @@ -265,11 +256,6 @@ {collaborators} {couponId} /> - {:else} {/if} diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index 7fd39a911b..f300a7bd0f 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -4,10 +4,7 @@ import { page } from '$app/stores'; import { Submit, trackError, trackEvent } from '$lib/actions/analytics'; import { Alert } from '$lib/components'; - import { - PlanComparisonBox, - SelectPaymentMethod - } from '$lib/components/billing'; + import { PlanComparisonBox, SelectPaymentMethod } from '$lib/components/billing'; import EstimatedTotal from '$lib/components/billing/estimatedTotal.svelte'; import PlanExcess from '$lib/components/billing/planExcess.svelte'; import SelectPlan from '$lib/components/billing/selectPlan.svelte'; @@ -299,10 +296,7 @@ >Your contract is not eligible for manual changes. Please reach out to schedule a call or setup a dialog. {/if} - + {#if isDowngrade} {#if billingPlan === BillingPlan.FREE} @@ -338,20 +332,13 @@ validityMessage="Invalid email address" id="members" /> +
    - {#if !couponData?.code} - - {/if} {/if} - - - {#if isDowngrade} Date: Wed, 15 Jan 2025 08:59:36 +0000 Subject: [PATCH 034/231] fix history not showing --- .../organization-[organization]/billing/paymentHistory.svelte | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte index 8a50a4efc3..5ee85510ca 100644 --- a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte +++ b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte @@ -62,8 +62,7 @@ request(); } - -{#if $organization?.billingPlan === BillingPlan.FREE && invoiceList.total > 0} +{#if $organization?.billingPlan !== BillingPlan.FREE && invoiceList.total > 0} Payment history From dee3b530debaabfebae519b517eff22894d2a7bb Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 15 Jan 2025 09:33:57 +0000 Subject: [PATCH 035/231] fix summary --- src/lib/sdk/billing.ts | 4 +++- .../billing/+page.svelte | 1 + .../billing/planSummary.svelte | 18 ++++++++---------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index d3078688c9..0d0824561d 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -171,10 +171,12 @@ export type Aggregation = { * Total amount of the invoice. */ amount: number; + additionalMembers: number; + /** * Price for additional members */ - additionalMembers: number; + additionalMemberAmount: number; /** * Total storage usage. */ diff --git a/src/routes/(console)/organization-[organization]/billing/+page.svelte b/src/routes/(console)/organization-[organization]/billing/+page.svelte index 25b35dc327..cc0fb72d17 100644 --- a/src/routes/(console)/organization-[organization]/billing/+page.svelte +++ b/src/routes/(console)/organization-[organization]/billing/+page.svelte @@ -123,6 +123,7 @@ creditList={data?.creditList} members={data?.members} currentPlan={data?.aggregationBillingPlan} + currentAggregation={data?.billingAggregation} currentInvoice={data?.billingInvoice} /> diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte index a2b3f05ced..3d8a89c6d4 100644 --- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte +++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte @@ -5,7 +5,7 @@ import { toLocaleDate } from '$lib/helpers/date'; import { plansInfo, tierToPlan, upgradeURL } from '$lib/stores/billing'; import { organization } from '$lib/stores/organization'; - import type { CreditList, Invoice, Plan } from '$lib/sdk/billing'; + import type { Aggregation, CreditList, Invoice, Plan } from '$lib/sdk/billing'; import { abbreviateNumber, formatCurrency, formatNumberWithCommas } from '$lib/helpers/numbers'; import { humanFileSize } from '$lib/helpers/sizeConvertion'; import { BillingPlan } from '$lib/constants'; @@ -18,17 +18,16 @@ export let currentPlan: Plan; export let creditList: CreditList; export let currentInvoice: Invoice | undefined = undefined; + export let currentAggregation: Aggregation | undefined = undefined let showCancel: boolean = false; - const extraMembers = members.total > 1 ? members.total - 1 : 0; const availableCredit = creditList.available; const today = new Date(); const isTrial = new Date($organization?.billingStartDate).getTime() - today.getTime() > 0 && $plansInfo.get($organization.billingPlan)?.trialDays; const extraUsage = currentInvoice ? currentInvoice.amount - currentPlan?.price : 0; - const extraAddons = currentInvoice ? currentInvoice.usage?.length : 0; {#if $organization} @@ -64,7 +63,7 @@ Add-ons{extraMembers ? extraAddons + 1 : extraAddons} + >{currentAggregation.additionalMembers > 0 ? currentInvoice.usage.length + 1 : currentInvoice.usage.length}
    @@ -78,7 +77,7 @@
      - {#if extraMembers} + {#if currentAggregation.additionalMembers}
    • @@ -86,15 +85,14 @@
      {formatCurrency( - extraMembers * - (currentPlan?.addons?.seats?.price ?? 0) + currentAggregation.additionalMemberAmount )}
      - {extraMembers} + {currentAggregation.additionalMembers}
    • @@ -102,10 +100,10 @@ {#if currentInvoice?.usage} {#each currentInvoice.usage as excess, i}
    • 0 ? 'u-padding-block-8' : 'u-padding-block-start-8'}" - class:u-sep-block-start={i > 0 || extraMembers}> + class:u-sep-block-start={i > 0 || currentAggregation.additionalMembers > 0}> {#if ['storage', 'bandwidth'].includes(excess.name)} {@const excessValue = humanFileSize( excess.value From e879bbd07664bcb889ed19859df21f7fb1058385 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 19 Jan 2025 12:01:37 +0530 Subject: [PATCH 036/231] fix: broken flags due to invalid or non-existing project IDs. --- src/lib/elements/flag.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/elements/flag.svelte b/src/lib/elements/flag.svelte index d1dfe28494..560df6a5c1 100644 --- a/src/lib/elements/flag.svelte +++ b/src/lib/elements/flag.svelte @@ -12,7 +12,7 @@ export function getFlag(country: string, width: number, height: number, quality: number) { if (!isValueOfStringEnum(Flag, country)) return ''; - let flag = sdk.forProject.avatars + let flag = sdk.forConsole.avatars .getFlag(country, width * 2, height * 2, quality) ?.toString(); flag?.includes('&project=') From 654718d019cd4b41ae2c73e116e9b072cbd406f3 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 19 Jan 2025 07:31:42 +0000 Subject: [PATCH 037/231] fix errors --- .../components/billing/estimatedTotal.svelte | 23 +++++++++---------- .../(console)/apply-credit/+page.svelte | 1 + .../create-organization/+page.svelte | 2 +- .../change-plan/+page.svelte | 1 + 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/lib/components/billing/estimatedTotal.svelte b/src/lib/components/billing/estimatedTotal.svelte index f39f94f96e..fa7a3b34ea 100644 --- a/src/lib/components/billing/estimatedTotal.svelte +++ b/src/lib/components/billing/estimatedTotal.svelte @@ -1,4 +1,6 @@ -{#if estimation} +{#if isDowngrade} +
      + +

      + Your change will take effect once your current billing cycle ends on {toLocaleDate($organization.billingNextInvoiceDate)}. +

      +
      + +{:else if estimation}
      { if ($page.url.searchParams.has('coupon')) { - const coupon = $page.url.searchParams.get('coupon'); - try { - const response = await sdk.forConsole.billing.getCoupon(coupon); - couponData = response; - } catch (e) { - couponData = { - code: null, - status: null, - credits: null - }; - } + couponId = $page.url.searchParams.get('coupon'); } if ($page.url.searchParams.has('name')) { name = $page.url.searchParams.get('name'); @@ -152,7 +142,7 @@ billingPlan, paymentMethodId, null, - couponData?.code, + couponId, collaborators, billingBudget, taxId diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index 025d739863..35c358b604 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -360,12 +360,22 @@ {#if billingPlan !== BillingPlan.FREE && $organization.billingPlan !== billingPlan && $organization.billingPlan !== BillingPlan.CUSTOM && isUpgrade} {:else if $organization.billingPlan !== BillingPlan.CUSTOM} + {#if isDowngrade} + + {/if} {/if} From d64de9039de649249c402b370cfc2626045cffa8 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 20 Jan 2025 06:41:18 +0000 Subject: [PATCH 039/231] improve estimatie total --- .../components/billing/estimatedTotal.svelte | 162 +++++++++--------- .../change-plan/+page.svelte | 30 ++-- 2 files changed, 102 insertions(+), 90 deletions(-) diff --git a/src/lib/components/billing/estimatedTotal.svelte b/src/lib/components/billing/estimatedTotal.svelte index fef5436088..1af444fd36 100644 --- a/src/lib/components/billing/estimatedTotal.svelte +++ b/src/lib/components/billing/estimatedTotal.svelte @@ -1,21 +1,17 @@ -{#if isDowngrade} -
      - -

      - Your change will take effect once your current billing cycle ends on {toLocaleDate($organization.billingNextInvoiceDate)}. -

      -
      - +{#if error.length} + + + {error} + + {:else if estimation} - -
      - - {#each estimation.items ?? [] as item} +
      + + {#each estimation.items ?? [] as item} + +

      {item.label}

      +

      {formatCurrency(item.value)}

      +
      + {/each} + {#each estimation.discounts ?? [] as item} + + {/each} +
      -

      {item.label}

      -

      {formatCurrency(item.value)}

      +

      + Total due
      +

      +

      + {formatCurrency(estimation.grossAmount)} +

      - {/each} - {#each estimation.discounts ?? [] as item} - - {/each} -
      - -

      - Total due
      -

      -

      - {formatCurrency(estimation.grossAmount)} -

      -
      -

      - You'll pay {formatCurrency(estimation.amount)} now. Once your credits run out, you'll be charged - {formatCurrency(estimation.amount)} every 30 days. -

      +

      + You'll pay {formatCurrency(estimation.amount)} now. Once + your credits run out, you'll be charged + {formatCurrency(estimation.amount)} every 30 days. +

      - - - {#if budgetEnabled} -
      - -
      - {/if} -
      -
      -
      -{/if} \ No newline at end of file + + + {#if budgetEnabled} +
      + +
      + {/if} +
      +
      +
      +{/if} diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index 35c358b604..baf1f44ccb 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -21,6 +21,7 @@ InputTextarea, Label } from '$lib/elements/forms'; + import { toLocaleDate } from '$lib/helpers/date.js'; import { formatCurrency } from '$lib/helpers/numbers'; import { WizardSecondaryContainer, @@ -76,6 +77,7 @@ let taxId: string; let billingBudget: number; let showCreditModal = false; + let error: string = ''; let feedbackDowngradeReason: string; let feedbackMessage: string; @@ -83,6 +85,7 @@ onMount(async () => { if ($page.url.searchParams.has('code')) { + couponId = $page.url.searchParams.get('code'); const coupon = $page.url.searchParams.get('code'); try { const response = await sdk.forConsole.billing.getCoupon(coupon); @@ -275,7 +278,7 @@ $: if (billingPlan !== BillingPlan.FREE) { loadPaymentMethods(); } - $: isButtonDisabled = $organization.billingPlan === billingPlan; + $: isButtonDisabled = $organization.billingPlan === billingPlan || error.length > 0; @@ -360,21 +363,26 @@ {#if billingPlan !== BillingPlan.FREE && $organization.billingPlan !== billingPlan && $organization.billingPlan !== BillingPlan.CUSTOM && isUpgrade} {:else if $organization.billingPlan !== BillingPlan.CUSTOM} {#if isDowngrade} - +
      + +

      + Your change will take effect once your current billing cycle ends on {toLocaleDate($organization.billingNextInvoiceDate)}. +

      +
      {/if} {/if} @@ -386,7 +394,7 @@ From e696d0c05b667ef1478ae01819f31fffe6391315 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 20 Jan 2025 06:41:36 +0000 Subject: [PATCH 040/231] check estimation before delete flow --- .../settings/+page.svelte | 2 + .../deleteOrganizationEstimation.svelte | 31 +++ .../settings/deleteOrganizationModal.svelte | 203 +++++++++--------- .../settings/invoicesTable.svelte | 137 ++++++++++++ 4 files changed, 276 insertions(+), 97 deletions(-) create mode 100644 src/routes/(console)/organization-[organization]/settings/deleteOrganizationEstimation.svelte create mode 100644 src/routes/(console)/organization-[organization]/settings/invoicesTable.svelte diff --git a/src/routes/(console)/organization-[organization]/settings/+page.svelte b/src/routes/(console)/organization-[organization]/settings/+page.svelte index 98b236e6d7..361a52d73e 100644 --- a/src/routes/(console)/organization-[organization]/settings/+page.svelte +++ b/src/routes/(console)/organization-[organization]/settings/+page.svelte @@ -15,10 +15,12 @@ import { isCloud } from '$lib/system'; import Baa from './BAA.svelte'; import Soc2 from './Soc2.svelte'; + import DeleteOrganizationEstimation from './deleteOrganizationEstimation.svelte'; export let data; let name: string; let showDelete = false; + let showDeleteEstimation = false; onMount(() => { name = $organization.name; diff --git a/src/routes/(console)/organization-[organization]/settings/deleteOrganizationEstimation.svelte b/src/routes/(console)/organization-[organization]/settings/deleteOrganizationEstimation.svelte new file mode 100644 index 0000000000..3d6a967b9d --- /dev/null +++ b/src/routes/(console)/organization-[organization]/settings/deleteOrganizationEstimation.svelte @@ -0,0 +1,31 @@ + + +{#if error} + + {error} + +{/if} +{#if estimation} + {#if estimation.unpaidInvoices?.length > 0} + + + You have a unpaid invoices. Please settle them first in order to delete team. + + + + + {/if} +{/if} + +{#if $selectedInvoice} + +{/if} diff --git a/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte b/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte index 78c9e29463..26a3384917 100644 --- a/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte +++ b/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte @@ -1,5 +1,5 @@
      @@ -108,102 +124,95 @@ icon="exclamation" state="warning" headerDivider={false}> - {#if upcomingInvoice} - - - You have a pending {formatCurrency(upcomingInvoice.grossAmount)} invoice for your - {tierToPlan(upcomingInvoice.plan).name} plan - -

      - By proceeding, your invoice will be processed within the hour. Upon successful - payment, your organization will be deleted. -

      -
      - {/if} + {#if estimation} + + {:else} +

      + {#if $projects.total > 0} + The following projects and all data associated with {$organization.name} + will be permanently deleted. This action is irreversible. + {:else} + All data associated with {$organization.name} will be permanently + deleted. + This action is irreversible. + {/if} +

      -

      {#if $projects.total > 0} - The following projects and all data associated with {$organization.name} will - be permanently deleted. This action is irreversible. - {:else} - All data associated with {$organization.name} will be permanently deleted. - This action is irreversible. - {/if} -

      - - {#if $projects.total > 0} -
      - - {#each tabs as { name, label, total }} - (selectedTab = name)}> - {label.desktop} ({total}) - - {/each} - - - - - {#each tabData.headers as header} - {header} - {/each} - - - {#each tabData.rows as row} - - {#each row.cells as cell} - {cell} - {/each} - - {/each} - - -
      -
      - - {#each tabs as { name, label, total }} - (selectedTab = name)}> - {label.mobile} ({total}) - - {/each} - - - - - {#each tabData.headers as header, index} - {header} +
      + + {#each tabs as { name, label, total }} + (selectedTab = name)}> + {label.desktop} ({total}) + {/each} - - - {#each tabData.rows as row} - - {#each row.cells as cell, index} - {cell} - {/each} - + + + + + {#each tabData.headers as header} + {header} + {/each} + + + {#each tabData.rows as row} + + {#each row.cells as cell} + {cell} + {/each} + + {/each} + + +
      +
      + + {#each tabs as { name, label, total }} + (selectedTab = name)}> + {label.mobile} ({total}) + {/each} - - -
      - {/if} + + + + + {#each tabData.headers as header, index} + {header} + {/each} + + + {#each tabData.rows as row} + + {#each row.cells as cell, index} + {cell} + {/each} + + {/each} + + +
      + {/if} - - - + + + + {/if} diff --git a/src/routes/(console)/organization-[organization]/settings/invoicesTable.svelte b/src/routes/(console)/organization-[organization]/settings/invoicesTable.svelte new file mode 100644 index 0000000000..fccee4c6a2 --- /dev/null +++ b/src/routes/(console)/organization-[organization]/settings/invoicesTable.svelte @@ -0,0 +1,137 @@ + + + + + Due Date + Status + Amount Due + + + + {#each invoices as invoice, i} + {@const status = invoice.status} + + + {toLocaleDate(invoice.dueAt)} + + + {#if invoice?.lastError} + + + {status === 'requires_authentication' ? 'failed' : status} + + +
    • + The scheduled payment has failed. + + . +
    • +
      +
      + {:else} + + {status === 'requires_authentication' ? 'failed' : status} + + {/if} +
      + + {formatCurrency(invoice.grossAmount)} + + + + + + (showDropdown[i] = !showDropdown[i])} + event="view_invoice"> + View invoice + + { + showDropdown[i] = !showDropdown[i]; + }} + event="download_invoice"> + Download PDF + + {#if status === 'overdue' || status === 'failed'} + { + retryPayment(invoice); + showDropdown[i] = !showDropdown[i]; + trackEvent(`click_retry_payment`, { + from: 'button', + source: 'billing_invoice_menu' + }); + }}> + Retry payment + + {/if} + + + +
      + {/each} +
      +
      From 2f36ff286bc2d4aceec436af7ab3edefeccc2c09 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 20 Jan 2025 06:42:13 +0000 Subject: [PATCH 041/231] remove unused code --- .../(console)/organization-[organization]/settings/+page.svelte | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/settings/+page.svelte b/src/routes/(console)/organization-[organization]/settings/+page.svelte index 361a52d73e..98b236e6d7 100644 --- a/src/routes/(console)/organization-[organization]/settings/+page.svelte +++ b/src/routes/(console)/organization-[organization]/settings/+page.svelte @@ -15,12 +15,10 @@ import { isCloud } from '$lib/system'; import Baa from './BAA.svelte'; import Soc2 from './Soc2.svelte'; - import DeleteOrganizationEstimation from './deleteOrganizationEstimation.svelte'; export let data; let name: string; let showDelete = false; - let showDeleteEstimation = false; onMount(() => { name = $organization.name; From 09ba6186d6c3a4949fd970c4ebe94304dde43b94 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Mon, 20 Jan 2025 08:26:04 +0000 Subject: [PATCH 042/231] fix check --- .../settings/deleteOrganizationModal.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte b/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte index 26a3384917..96073a0460 100644 --- a/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte +++ b/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte @@ -124,7 +124,7 @@ icon="exclamation" state="warning" headerDivider={false}> - {#if estimation} + {#if estimation &&( estimation.unpaidInvoices.length > 0 || estimation.grossAmount > 0)} {:else}

      From 39d82f7f35afadf81c3ce085ca626c8473e4ed1c Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 20 Jan 2025 18:11:50 +0530 Subject: [PATCH 043/231] fix: interceptor interfering on wrong steps. --- src/lib/layout/wizard.svelte | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/layout/wizard.svelte b/src/lib/layout/wizard.svelte index 56df886582..95f462c077 100644 --- a/src/lib/layout/wizard.svelte +++ b/src/lib/layout/wizard.svelte @@ -62,6 +62,8 @@ const step = e.detail; if (step < $wizard.step) { $wizard.step = step; + // clear the interceptor + wizard.setInterceptor(null); } } From 6e249cdd72979b51f8a749a27206da3e61eace86 Mon Sep 17 00:00:00 2001 From: ernstmul Date: Mon, 20 Jan 2025 15:51:07 +0100 Subject: [PATCH 044/231] Set limit to 100 --- .../collection-[collection]/attributes/relationship.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/routes/(console)/project-[project]/databases/database-[database]/collection-[collection]/attributes/relationship.svelte b/src/routes/(console)/project-[project]/databases/database-[database]/collection-[collection]/attributes/relationship.svelte index 1af15500bc..600c3fbb8b 100644 --- a/src/routes/(console)/project-[project]/databases/database-[database]/collection-[collection]/attributes/relationship.svelte +++ b/src/routes/(console)/project-[project]/databases/database-[database]/collection-[collection]/attributes/relationship.svelte @@ -92,7 +92,9 @@ ); return collections; } else { - const collections = await sdk.forProject.databases.listCollections(databaseId); + const collections = await sdk.forProject.databases.listCollections(databaseId, [ + Query.limit(100) + ]); return collections; } } From 5a1e391752c70b0048787e4266be83cd41251cb0 Mon Sep 17 00:00:00 2001 From: Arman Date: Wed, 22 Jan 2025 15:30:09 +0100 Subject: [PATCH 045/231] chore: enable scale plan --- .../billing/planComparisonBox.svelte | 6 +-- .../components/billing/planSelection.svelte | 46 ++++++++----------- src/routes/(console)/onboarding/+page.svelte | 8 ++-- 3 files changed, 27 insertions(+), 33 deletions(-) diff --git a/src/lib/components/billing/planComparisonBox.svelte b/src/lib/components/billing/planComparisonBox.svelte index c48dabfc38..e297d8e753 100644 --- a/src/lib/components/billing/planComparisonBox.svelte +++ b/src/lib/components/billing/planComparisonBox.svelte @@ -1,7 +1,7 @@ + + + + diff --git a/src/routes/(console)/project-[project]/databases/usage/[[period]]/+page.svelte b/src/routes/(console)/project-[project]/databases/usage/[[period]]/+page.svelte index d261dd5f98..a313f3d56c 100644 --- a/src/routes/(console)/project-[project]/databases/usage/[[period]]/+page.svelte +++ b/src/routes/(console)/project-[project]/databases/usage/[[period]]/+page.svelte @@ -7,6 +7,13 @@ export let data: PageData; $: total = data.databasesTotal; $: count = data.databases; + + // types need to be added to console sdk. + $: reads = data.databasesReads; + $: readsTotal = data.databasesReadsTotal; + + $: writes = data.databasesWrites; + $: writesTotal = data.databasesWritesTotal; + + + + diff --git a/src/routes/(console)/project-[project]/settings/usage/[[invoice]]/+page.svelte b/src/routes/(console)/project-[project]/settings/usage/[[invoice]]/+page.svelte index 49a6215280..8fe58f0c7b 100644 --- a/src/routes/(console)/project-[project]/settings/usage/[[invoice]]/+page.svelte +++ b/src/routes/(console)/project-[project]/settings/usage/[[invoice]]/+page.svelte @@ -37,6 +37,12 @@ data.usage.deploymentsStorageTotal + data.usage.buildsStorageTotal; + // types need to be added to console sdk. + $: dbReads = data.usage.databasesReads; + $: dbReadsTotal = data.usage.databasesReadsTotal; + $: dbWrites = data.usage.databasesWrites; + $: dbWritesTotal = data.usage.databasesWritesTotal; + const tier = data?.currentInvoice?.plan ?? $organization?.billingPlan; const plan = tierToPlan(tier).name; @@ -196,6 +202,55 @@ {/if} + + Database reads and writes + +

      Total database reads and writes in your project.

      + + + {#if dbReads || dbWrites} + {@const currentReads = formatNum(dbReadsTotal)} + {@const currentWrites = formatNum(dbWritesTotal)} + +
      +
      +

      + {currentReads}/{currentWrites} + Reads/Writes +

      +
      +
      + [e.date, e.value])] + }, + { + name: 'Writes', + data: [...dbWrites.map((e) => [e.date, e.value])] + } + ]} /> + {:else} + +
      +
      +
      + {/if} +
      + Executions From cb7650e5259062d797d9b20d6afe1a704da00f7a Mon Sep 17 00:00:00 2001 From: Arman Date: Thu, 23 Jan 2025 15:43:39 +0100 Subject: [PATCH 051/231] update: improve descriptions for billing tiers --- src/lib/stores/billing.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index 9b42358d15..a5b00f43e8 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -175,7 +175,7 @@ export type TierData = { export const tierFree: TierData = { name: 'Free', - description: 'For personal hobby projects of small scale and students.' + description: 'A great fit for passion projects and small applications.' }; export const tierGitHubEducation: TierData = { @@ -185,11 +185,13 @@ export const tierGitHubEducation: TierData = { export const tierPro: TierData = { name: 'Pro', - description: 'For pro developers and production projects that need the ability to scale.' + description: + 'For production applications that need powerful functionality and resources to scale.' }; export const tierScale: TierData = { name: 'Scale', - description: 'For scaling teams and agencies that need dedicated support.' + description: + 'For teams that handle more complex and large projects and need more control and support.' }; export const tierCustom: TierData = { From e048f6bdd99bab8e5dbfa5a3ef3d2ec30dadf844 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 24 Jan 2025 09:54:44 +0530 Subject: [PATCH 052/231] fix: payment history not visible. --- .../billing/paymentHistory.svelte | 262 +++++++++--------- 1 file changed, 135 insertions(+), 127 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte index ea6265f7c1..dd3b9ecf76 100644 --- a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte +++ b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte @@ -29,10 +29,10 @@ import { trackEvent } from '$lib/actions/analytics'; import { selectedInvoice, showRetryModal } from './store'; import { organization } from '$lib/stores/organization'; - import { BillingPlan } from '$lib/constants'; let showDropdown = []; let showFailedError = false; + let isLoadingInvoices = true; let offset = 0; let invoiceList: InvoiceList = { @@ -46,6 +46,7 @@ onMount(request); async function request() { + isLoadingInvoices = true; invoiceList = await sdk.forConsole.billing.listInvoices($page.params.organization, [ Query.limit(limit), Query.offset(offset), @@ -53,6 +54,7 @@ Query.notEqual('status', 'pending'), Query.orderDesc('$createdAt') ]); + isLoadingInvoices = false; } function retryPayment(invoice: Invoice) { @@ -65,144 +67,150 @@ } -{#if $organization?.billingPlan === BillingPlan.FREE && invoiceList.total > 0} - - Payment history + + Payment history -

      - Transaction history for this organization. Download invoices for more details about your - payments. -

      - - {#if invoiceList.total > 0} - - - Due Date - Status - Amount Due - - - - {#each invoiceList?.invoices as invoice, i} - {@const status = invoice.status} - - - {toLocaleDate(invoice.dueAt)} - - - {#if invoice?.lastError} - - (showFailedError = true)} - button> - {status === 'requires_authentication' - ? 'failed' - : status} - - -
    • - The scheduled payment has failed. - - . -
    • -
      -
      - {:else} +

      + Transaction history for this organization. Download invoices for more details about your + payments. +

      + + {#if invoiceList.total > 0} + + + Due Date + Status + Amount Due + + + + {#each invoiceList?.invoices as invoice, i} + {@const status = invoice.status} + + + {toLocaleDate(invoice.dueAt)} + + + {#if invoice?.lastError} + + warning={status === 'pending'} + on:click={() => (showFailedError = true)} + button> {status === 'requires_authentication' ? 'failed' : status} - {/if} - - - {formatCurrency(invoice.grossAmount)} - - - - - - (showDropdown[i] = !showDropdown[i])} - event="view_invoice"> - View invoice - - { - showDropdown[i] = !showDropdown[i]; - }} - event="download_invoice"> - Download PDF - - {#if status === 'overdue' || status === 'failed'} - + The scheduled payment has failed. + + . +
    • - - - {/each} - - -
      -

      Total results: {invoiceList?.total ?? 0}

      - -
      - {:else} - -

      - You have no payment history. After you receive your first invoice, you'll - see it here. -

      -
      - {/if} - - -{/if} + {:else} + + {status === 'requires_authentication' ? 'failed' : status} + + {/if} + + + {formatCurrency(invoice.grossAmount)} + + + + + + (showDropdown[i] = !showDropdown[i])} + event="view_invoice"> + View invoice + + { + showDropdown[i] = !showDropdown[i]; + }} + event="download_invoice"> + Download PDF + + {#if status === 'overdue' || status === 'failed'} + { + retryPayment(invoice); + showDropdown[i] = !showDropdown[i]; + trackEvent(`click_retry_payment`, { + from: 'button', + source: 'billing_invoice_menu' + }); + }}> + Retry payment + + {/if} + + + + + {/each} + + +
      +

      Total results: {invoiceList.total}

      + +
      + {:else if isLoadingInvoices} +
      +
      +
      + {:else} + +

      + You have no payment history. After you receive your first invoice, you'll see it + here. +

      +
      + {/if} + + + + From 884c454c55c72dcbbcba6c6982bc81dca40a7e2c Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 24 Jan 2025 13:01:08 +0530 Subject: [PATCH 053/231] add: database read, writes in org. usage screen. --- .../usage/[[invoice]]/+page.svelte | 62 +++++++++ .../usage/[[invoice]]/ProjectBreakdown.svelte | 121 ++++++++++++++---- 2 files changed, 160 insertions(+), 23 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte index 3cebea75e6..77096eb10f 100644 --- a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte +++ b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte @@ -193,6 +193,65 @@ + + Databases reads and writes + +

      + The total number of database reads and writes across all projects in your organization. +

      + + + {#if data.organizationUsage.databasesReadsTotal || data.organizationUsage.databasesWritesTotal} +
      + [ + e.date, + e.value + ]) + ] + }, + { + name: 'Writes', + data: [ + ...data.organizationUsage.databasesWrites.map((e) => [ + e.date, + e.value + ]) + ] + } + ]} /> +
      + {#if project?.length > 0} + + {/if} + {:else} + +
      +
      +
      + {/if} +
      +
      + Executions @@ -318,6 +377,7 @@ {/if} + GB hours @@ -378,6 +438,7 @@ {/if} + Phone OTP

      @@ -430,6 +491,7 @@ {/if} +

      diff --git a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/ProjectBreakdown.svelte b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/ProjectBreakdown.svelte index 8542fe75c5..7bd50227c2 100644 --- a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/ProjectBreakdown.svelte +++ b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/ProjectBreakdown.svelte @@ -15,14 +15,26 @@ import type { OrganizationUsage } from '$lib/sdk/billing'; import { base } from '$app/paths'; import { canSeeProjects } from '$lib/stores/roles'; + import { onMount } from 'svelte'; + + type Metric = + | 'users' + | 'storage' + | 'bandwidth' + | 'executions' + | 'authPhoneTotal' + | 'databasesReads' + | 'databasesWrites'; - type Metric = 'users' | 'storage' | 'bandwidth' | 'executions' | 'authPhoneTotal'; type Estimate = 'authPhoneEstimate'; + type DatabaseOperationMetric = Extract; + export let data: PageData; export let projects: OrganizationUsage['projects']; - export let metric: Metric; + export let metric: Metric | undefined = undefined; export let estimate: Estimate | undefined = undefined; + export let databaseOperationMetric: DatabaseOperationMetric[] | undefined = undefined; function getMetricTitle(metric: Metric): string { switch (metric) { @@ -38,25 +50,48 @@ } function groupByProject( - metric: Metric, - estimate?: Estimate - ): Array<{ projectId: string; usage: number; estimate?: number }> { + metric: Metric | undefined, + estimate?: Estimate, + databaseOps?: DatabaseOperationMetric[] + ): Array<{ + projectId: string; + databasesReads?: number; + databasesWrites?: number; + usage?: number; + estimate?: number; + }> { const data = []; for (const project of projects) { - const usage = project[metric]; - if (!usage) { - continue; + if (metric) { + const usage = project[metric]; + if (!usage) continue; + + data.push({ + projectId: project.projectId, + usage: usage ?? 0, + estimate: estimate ? project[estimate] : undefined + }); + } else if (databaseOps) { + const reads = project['databasesReads'] ?? 0; + const writes = project['databasesWrites'] ?? 0; + + if (reads || writes) { + data.push({ + projectId: project.projectId, + databasesReads: reads, + databasesWrites: writes + }); + } } - data.push({ - projectId: project.projectId, - usage: usage ?? 0, - estimate: estimate ? project[estimate] : undefined - }); } return data; } function format(value: number): string { + if (databaseOperationMetric) { + return abbreviateNumber(value); + } + switch (metric) { case 'authPhoneTotal': return formatNumberWithCommas(value); @@ -68,6 +103,12 @@ return humanFileSize(value).value + humanFileSize(value).unit; } } + + onMount(() => { + if (metric === undefined && databaseOperationMetric === undefined) { + throw new Error(`metric or database operations must be defined`); + } + }); @@ -76,7 +117,13 @@ Project - {getMetricTitle(metric)} + {#if databaseOperationMetric} + Reads + Writes + {:else} + {getMetricTitle(metric)} + {/if} + {#if estimate} Estimated cost {/if} @@ -85,17 +132,33 @@ {/if} - {#each groupByProject(metric, estimate).sort((a, b) => b.usage - a.usage) as project} + {#each groupByProject(metric, estimate, databaseOperationMetric).sort((a, b) => { + const aValue = a.usage ?? a.databasesReads ?? 0; + const bValue = b.usage ?? b.databasesReads ?? 0; + return bValue - aValue; + }) as project} {#if !$canSeeProjects} {data.projectNames[project.projectId]?.name ?? 'Unknown'} - {format(project.usage)} + {#if databaseOperationMetric} + + {format(project.databasesReads ?? 0)} + + + {format(project.databasesWrites ?? 0)} + + {:else} + + {format(project.usage)} + + {/if} + {#if project.estimate} - {formatCurrency(project.estimate)} + + {formatCurrency(project.estimate)} + {/if} {:else} @@ -103,11 +166,23 @@ {data.projectNames[project.projectId]?.name ?? 'Unknown'} - {format(project.usage)} + {#if databaseOperationMetric} + + {format(project.databasesReads ?? 0)} + + + {format(project.databasesWrites ?? 0)} + + {:else} + + {format(project.usage)} + + {/if} + {#if project.estimate} - {formatCurrency(project.estimate)} + + {formatCurrency(project.estimate)} + {/if} Date: Fri, 24 Jan 2025 13:12:06 +0530 Subject: [PATCH 054/231] remove: leftovers. --- .../usage/[[invoice]]/+page.svelte | 6 +++--- .../database-[database]/usage/[[period]]/+page.svelte | 5 ----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte index 77096eb10f..bcd97f80d0 100644 --- a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte +++ b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte @@ -201,7 +201,7 @@

      - {#if data.organizationUsage.databasesReadsTotal || data.organizationUsage.databasesWritesTotal} + {#if data.organizationUsage.databasesReads || data.organizationUsage.databasesWrites}
      [ + ...(data.organizationUsage.databasesReads ?? []).map((e) => [ e.date, e.value ]) @@ -224,7 +224,7 @@ { name: 'Writes', data: [ - ...data.organizationUsage.databasesWrites.map((e) => [ + ...(data.organizationUsage.databasesWrites ?? []).map((e) => [ e.date, e.value ]) diff --git a/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte b/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte index 23e2ba5309..68297576c9 100644 --- a/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte +++ b/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte @@ -3,7 +3,6 @@ import { page } from '$app/stores'; import { Usage } from '$lib/layout'; import type { PageData } from './$types'; - import { onMount } from 'svelte'; export let data: PageData; @@ -16,10 +15,6 @@ $: writes = data.databaseWrites; $: writesTotal = data.databaseWritesTotal; - - onMount(() => { - console.log([readsTotal, writesTotal]); - }); Date: Fri, 24 Jan 2025 13:38:05 +0530 Subject: [PATCH 055/231] add: types for org-usage modal. --- src/lib/sdk/billing.ts | 4 ++++ .../organization-[organization]/usage/[[invoice]]/+page.ts | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts index 95c9f5c77d..32e65b6a1e 100644 --- a/src/lib/sdk/billing.ts +++ b/src/lib/sdk/billing.ts @@ -179,9 +179,13 @@ export type Aggregation = { export type OrganizationUsage = { bandwidth: Array; executions: Array; + databasesReads: Array; + databasesWrites: Array; executionsTotal: number; filesStorageTotal: number; buildsStorageTotal: number; + databasesReadsTotal: number; + databasesWritesTotal: number; deploymentsStorageTotal: number; executionsMBSecondsTotal: number; buildsMBSecondsTotal: number; diff --git a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.ts b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.ts index 4138acfa16..967ee6d503 100644 --- a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.ts +++ b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.ts @@ -29,7 +29,11 @@ export const load: PageLoad = async ({ params, parent }) => { executionsMBSecondsTotal: null, buildsMBSecondsTotal: null, authPhoneTotal: null, - authPhoneEstimate: null + authPhoneEstimate: null, + databasesReads: null, + databasesWrites: null, + databasesReadsTotal: null, + databasesWritesTotal: null, } }; } From df94359c8eabbe460c1e8ad84650c29073ca4a9c Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 24 Jan 2025 14:00:25 +0530 Subject: [PATCH 056/231] skip: loader for now. --- .../billing/paymentHistory.svelte | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte index dd3b9ecf76..baee0abfec 100644 --- a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte +++ b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte @@ -32,7 +32,7 @@ let showDropdown = []; let showFailedError = false; - let isLoadingInvoices = true; + // let isLoadingInvoices = true; let offset = 0; let invoiceList: InvoiceList = { @@ -46,7 +46,7 @@ onMount(request); async function request() { - isLoadingInvoices = true; + // isLoadingInvoices = true; invoiceList = await sdk.forConsole.billing.listInvoices($page.params.organization, [ Query.limit(limit), Query.offset(offset), @@ -54,7 +54,7 @@ Query.notEqual('status', 'pending'), Query.orderDesc('$createdAt') ]); - isLoadingInvoices = false; + // isLoadingInvoices = false; } function retryPayment(invoice: Invoice) { @@ -192,10 +192,10 @@

      Total results: {invoiceList.total}

      - {:else if isLoadingInvoices} -
      -
      -
      + + + + {:else}

      @@ -207,10 +207,10 @@ - + + + + + + + From f143d34365787e52cb3cf3c6896d7da4b88a09f8 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 25 Jan 2025 19:34:35 +0530 Subject: [PATCH 057/231] new: custom legend and usage component. --- src/lib/charts/index.ts | 1 + src/lib/charts/legend.svelte | 23 +++++++++++ src/lib/layout/index.ts | 1 + src/lib/layout/usageMultiple.svelte | 63 +++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 src/lib/charts/legend.svelte create mode 100644 src/lib/layout/usageMultiple.svelte diff --git a/src/lib/charts/index.ts b/src/lib/charts/index.ts index c73108a134..488756ecb5 100644 --- a/src/lib/charts/index.ts +++ b/src/lib/charts/index.ts @@ -1,2 +1,3 @@ export { default as BarChart } from './bar.svelte'; export { default as LineChart } from './line.svelte'; +export { default as Legend, type LegendData } from './legend.svelte'; diff --git a/src/lib/charts/legend.svelte b/src/lib/charts/legend.svelte new file mode 100644 index 0000000000..671f4cce35 --- /dev/null +++ b/src/lib/charts/legend.svelte @@ -0,0 +1,23 @@ + + + + +

      + {#each legendData as { name, value }, index} +
      + + {name} ({value}) +
      + {/each} +
      diff --git a/src/lib/layout/index.ts b/src/lib/layout/index.ts index e45069dd11..fa8289f73b 100644 --- a/src/lib/layout/index.ts +++ b/src/lib/layout/index.ts @@ -13,6 +13,7 @@ export { default as WizardStep } from './wizardStep.svelte'; export { default as Breadcrumbs } from './breadcrumbs.svelte'; export { default as Unauthenticated } from './unauthenticated.svelte'; export { default as Usage, type UsagePeriods } from './usage.svelte'; +export { default as UsageMultiple } from './usageMultiple.svelte'; export { default as Activity } from './activity.svelte'; export { default as Progress } from './progress.svelte'; export { default as GridHeader } from './gridHeader.svelte'; diff --git a/src/lib/layout/usageMultiple.svelte b/src/lib/layout/usageMultiple.svelte new file mode 100644 index 0000000000..6e3d3be434 --- /dev/null +++ b/src/lib/layout/usageMultiple.svelte @@ -0,0 +1,63 @@ + + + +
      + {title} + {#if path} + + + 24h + + + 30d + + + 90d + + + {/if} +
      + + {#if count} +
      +
      + ({ + name: legendData[index].name, + data: accumulateFromEndingTotal(c, total[index]) + }))} /> +
      + + {#if legendData} + + {/if} +
      + {/if} +
      +
      + + From e3774be0aa323e24f43d4a0d68aed92f8d2a1de1 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 25 Jan 2025 19:37:10 +0530 Subject: [PATCH 058/231] update: use new usageMultiple component for database r&w metrics. --- .../usage/[[invoice]]/+page.svelte | 11 +++- .../usage/[[invoice]]/+page.ts | 2 +- .../usage/[[period]]/+page.svelte | 27 +++------ .../databases/usage/[[period]]/+page.svelte | 27 +++------ .../settings/usage/[[invoice]]/+page.svelte | 57 +++++++++---------- 5 files changed, 56 insertions(+), 68 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte index bcd97f80d0..b002e59f3c 100644 --- a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte +++ b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte @@ -10,7 +10,7 @@ import { organization } from '$lib/stores/organization'; import { Button } from '$lib/elements/forms'; import { bytesToSize, humanFileSize, mbSecondsToGBHours } from '$lib/helpers/sizeConvertion'; - import { BarChart } from '$lib/charts'; + import { BarChart, Legend } from '$lib/charts'; import ProjectBreakdown from './ProjectBreakdown.svelte'; import { formatNum } from '$lib/helpers/string'; import { accumulateFromEndingTotal, total } from '$lib/layout/usage.svelte'; @@ -29,6 +29,11 @@ const plan = data?.plan ?? undefined; $: project = (data.organizationUsage as OrganizationUsage).projects; + + $: legendData = [ + { name: 'Reads', value: data.organizationUsage.databasesReadsTotal }, + { name: 'Writes', value: data.organizationUsage.databasesWritesTotal } + ]; @@ -200,7 +205,6 @@ The total number of database reads and writes across all projects in your organization.

      - {#if data.organizationUsage.databasesReads || data.organizationUsage.databasesWrites}
      + + + {#if project?.length > 0} { databasesReads: null, databasesWrites: null, databasesReadsTotal: null, - databasesWritesTotal: null, + databasesWritesTotal: null } }; } diff --git a/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte b/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte index 68297576c9..fd5fd58755 100644 --- a/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte +++ b/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte @@ -1,7 +1,7 @@ @@ -60,10 +63,7 @@ {:else if estimation} -
      + {#each estimation.items ?? [] as item} @@ -85,9 +85,9 @@

      - You'll pay {formatCurrency(estimation.amount)} now. Once + You'll pay {formatCurrency(estimation.grossAmount)} now. Once your credits run out, you'll be charged - {formatCurrency(estimation.amount)} every 30 days. + {formatCurrency(estimation.grossAmount)} every 30 days.

      @@ -110,5 +110,5 @@ {/if} -
      + {/if} diff --git a/src/routes/(console)/apply-credit/+page.svelte b/src/routes/(console)/apply-credit/+page.svelte index 588bb5697b..f9cb293e31 100644 --- a/src/routes/(console)/apply-credit/+page.svelte +++ b/src/routes/(console)/apply-credit/+page.svelte @@ -288,7 +288,7 @@
      diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte index b1a8f28c87..b07f1eac31 100644 --- a/src/routes/(console)/create-organization/+page.svelte +++ b/src/routes/(console)/create-organization/+page.svelte @@ -142,7 +142,7 @@ billingPlan, paymentMethodId, null, - couponId, + couponId && couponId.length > 0 ? couponId : null, collaborators, billingBudget, taxId From dda2fd8792402d9563d8690310df06c999694b52 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 26 Jan 2025 06:19:49 +0000 Subject: [PATCH 060/231] update review comments --- src/lib/components/billing/estimatedTotal.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/billing/estimatedTotal.svelte b/src/lib/components/billing/estimatedTotal.svelte index 06e7cc48e8..0199e0ba96 100644 --- a/src/lib/components/billing/estimatedTotal.svelte +++ b/src/lib/components/billing/estimatedTotal.svelte @@ -77,7 +77,7 @@

      - Total due
      + Total due

      {formatCurrency(estimation.grossAmount)} From 8e994cba4ed814d684e3871f30ccfafd6bcb7326 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 26 Jan 2025 06:21:08 +0000 Subject: [PATCH 061/231] remove old component --- .../billing/estimatedTotalBox.svelte | 132 ------------------ src/lib/components/billing/index.ts | 1 - 2 files changed, 133 deletions(-) delete mode 100644 src/lib/components/billing/estimatedTotalBox.svelte diff --git a/src/lib/components/billing/estimatedTotalBox.svelte b/src/lib/components/billing/estimatedTotalBox.svelte deleted file mode 100644 index 4d96f87c4d..0000000000 --- a/src/lib/components/billing/estimatedTotalBox.svelte +++ /dev/null @@ -1,132 +0,0 @@ - - -

      - -
      -

      {selectedPlan.name} plan

      -

      {formatCurrency(selectedPlan.price)}

      -
      - -
      -

      Additional seats ({collaborators?.length})

      -

      - {formatCurrency( - isScaleDowngrade - ? (collaborators?.length ?? 0) * (selectedPlan?.addons?.seats?.price ?? 0) - : extraSeatsCost - )} -

      -
      - - {#if isScaleUpgrade} - {@const currentPlanName = currentOrgPlan.name} -
      -
      - Unused {currentPlanName} plan balance - - -
      -

      -{formatCurrency(unUsedBalances)}

      -
      - {/if} - - {#if couponData?.status === 'active'} - - {/if} -
      -
      -

      - Upcoming charge
      Due on {!selectedPlan.trialDays - ? toLocaleDate(billingPayDate.toString()) - : toLocaleDate(trialEndDate.toString())} -

      -

      - {formatCurrency(estimatedTotal)} -

      -
      - -

      - You'll pay {formatCurrency(estimatedTotal)} now, with your first - billing cycle starting on - {!currentOrgPlan.trialDays - ? toLocaleDate(billingPayDate.toString()) - : toLocaleDate(trialEndDate.toString())}. Once your credits run out, you'll be charged - {formatCurrency(currentOrgPlan.price)} plus usage fees every 30 days. -

      - - - - {#if budgetEnabled} -
      - -
      - {/if} -
      -
      -
      diff --git a/src/lib/components/billing/index.ts b/src/lib/components/billing/index.ts index 0643e5922d..f58efa2504 100644 --- a/src/lib/components/billing/index.ts +++ b/src/lib/components/billing/index.ts @@ -2,7 +2,6 @@ export { default as PaymentBoxes } from './paymentBoxes.svelte'; export { default as CouponInput } from './couponInput.svelte'; export { default as SelectPaymentMethod } from './selectPaymentMethod.svelte'; export { default as UsageRates } from './usageRates.svelte'; -export { default as EstimatedTotalBox } from './estimatedTotalBox.svelte'; export { default as PlanComparisonBox } from './planComparisonBox.svelte'; export { default as EmptyCardCloud } from './emptyCardCloud.svelte'; export { default as CreditsApplied } from './creditsApplied.svelte'; From 6e6daca8b49b1d0ec14ef27ec132dcf867554347 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 26 Jan 2025 06:26:09 +0000 Subject: [PATCH 062/231] removed unused change --- src/lib/stores/stripe.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/lib/stores/stripe.ts b/src/lib/stores/stripe.ts index e62110d209..58edfd4316 100644 --- a/src/lib/stores/stripe.ts +++ b/src/lib/stores/stripe.ts @@ -117,8 +117,7 @@ export async function confirmPayment( orgId: string, clientSecret: string, paymentMethodId: string, - route?: string, - returnError: boolean = false + route?: string ) { try { const url = @@ -134,9 +133,6 @@ export async function confirmPayment( } }); if (error) { - if (returnError) { - return error; - } throw error.message; } } catch (e) { From 27c545325507fb08743a812c8f5a35e10baa5c17 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 26 Jan 2025 06:36:27 +0000 Subject: [PATCH 063/231] more review fixes --- src/routes/(console)/create-organization/+page.svelte | 2 +- .../organization-[organization]/billing/+page.ts | 8 ++------ ...lDowngradeModel.svelte => cancelDowngradeModal.svelte} | 0 .../billing/planSummary.svelte | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) rename src/routes/(console)/organization-[organization]/billing/{cancelDowngradeModel.svelte => cancelDowngradeModal.svelte} (100%) diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte index b07f1eac31..914bddcb56 100644 --- a/src/routes/(console)/create-organization/+page.svelte +++ b/src/routes/(console)/create-organization/+page.svelte @@ -105,7 +105,7 @@ async function validate(organizationId: string, invites: string[]) { try { - let org = await sdk.forConsole.billing.validateOrganization(organizationId, invites); + const org = await sdk.forConsole.billing.validateOrganization(organizationId, invites); if (isOrganization(org)) { await preloadData(`${base}/console/organization-${org.$id}`); await goto(`${base}/console/organization-${org.$id}`); diff --git a/src/routes/(console)/organization-[organization]/billing/+page.ts b/src/routes/(console)/organization-[organization]/billing/+page.ts index 0d7f48a376..ef01264d7b 100644 --- a/src/routes/(console)/organization-[organization]/billing/+page.ts +++ b/src/routes/(console)/organization-[organization]/billing/+page.ts @@ -34,12 +34,6 @@ export const load: PageLoad = async ({ parent, depends }) => { } const billingInvoiceId = (organization as Organization)?.billingInvoiceId; - let billingInvoice = null; - try { - billingInvoice = await sdk.forConsole.billing.getInvoice(organization.$id, billingInvoiceId) - } catch (e) { - // ignore error - } const [ @@ -47,12 +41,14 @@ export const load: PageLoad = async ({ parent, depends }) => { addressList, billingAddress, creditList, + billingInvoice, aggregationBillingPlan, ] = await Promise.all([ sdk.forConsole.billing.listPaymentMethods(), sdk.forConsole.billing.listAddresses(), billingAddressPromise, sdk.forConsole.billing.listCredits(organization.$id), + sdk.forConsole.billing.getInvoice(organization.$id, billingInvoiceId), sdk.forConsole.billing.getPlan(billingAggregation?.plan ?? organization.billingPlan), ]); diff --git a/src/routes/(console)/organization-[organization]/billing/cancelDowngradeModel.svelte b/src/routes/(console)/organization-[organization]/billing/cancelDowngradeModal.svelte similarity index 100% rename from src/routes/(console)/organization-[organization]/billing/cancelDowngradeModel.svelte rename to src/routes/(console)/organization-[organization]/billing/cancelDowngradeModal.svelte diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte index 3d8a89c6d4..f88992b861 100644 --- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte +++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte @@ -12,7 +12,7 @@ import { trackEvent } from '$lib/actions/analytics'; import { tooltip } from '$lib/actions/tooltip'; import { type Models } from '@appwrite.io/console'; - import CancelDowngradeModel from './cancelDowngradeModel.svelte'; + import CancelDowngradeModel from './cancelDowngradeModal.svelte'; export let members: Models.MembershipList; export let currentPlan: Plan; From cc0f655a56437c9565e8385183724f143f0474f4 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 26 Jan 2025 06:39:14 +0000 Subject: [PATCH 064/231] fix component --- .../change-plan/+page.svelte | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index baf1f44ccb..de8a9f63eb 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -9,6 +9,7 @@ import PlanExcess from '$lib/components/billing/planExcess.svelte'; import SelectPlan from '$lib/components/billing/selectPlan.svelte'; import ValidateCreditModal from '$lib/components/billing/validateCreditModal.svelte'; + import Card from '$lib/components/card.svelte'; import Default from '$lib/components/roles/default.svelte'; import { BillingPlan, Dependencies, feedbackDowngradeOptions } from '$lib/constants'; import { @@ -363,26 +364,20 @@ {#if billingPlan !== BillingPlan.FREE && $organization.billingPlan !== billingPlan && $organization.billingPlan !== BillingPlan.CUSTOM && isUpgrade} {:else if $organization.billingPlan !== BillingPlan.CUSTOM} {#if isDowngrade} -
      - -

      - Your change will take effect once your current billing cycle ends on {toLocaleDate($organization.billingNextInvoiceDate)}. -

      -
      + + Your change will take effect once your current billing cycle ends on {toLocaleDate($organization.billingNextInvoiceDate)}. + {/if} {/if} @@ -394,7 +389,7 @@ From f3a28cd6685025b95965af7a9580330bd8259815 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 26 Jan 2025 06:42:43 +0000 Subject: [PATCH 065/231] remove duplicates --- src/lib/stores/billing.ts | 6 +++++- src/routes/(console)/create-organization/+page.svelte | 6 +----- .../organization-[organization]/change-plan/+page.svelte | 6 +----- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index 6604469cb2..ed2854ad99 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -1,7 +1,7 @@ import { page } from '$app/stores'; import { derived, get, writable } from 'svelte/store'; import { sdk } from './sdk'; -import { organization, type Organization } from './organization'; +import { organization, type Organization, type OrganizationError } from './organization'; import type { InvoiceList, AddressesList, @@ -485,3 +485,7 @@ export function calculateResourceSurplus(total: number, limit: number, limitUnit const realLimit = (limitUnit ? sizeToBytes(limit, limitUnit) : limit) || Infinity; return total > realLimit ? total - realLimit : 0; } + +export function isOrganization(org: Organization | OrganizationError): org is Organization { + return (org as Organization).$id !== undefined; +} \ No newline at end of file diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte index 914bddcb56..e84f8e1977 100644 --- a/src/routes/(console)/create-organization/+page.svelte +++ b/src/routes/(console)/create-organization/+page.svelte @@ -21,7 +21,7 @@ WizardSecondaryFooter } from '$lib/layout'; import type { Coupon, PaymentList } from '$lib/sdk/billing'; - import { tierToPlan } from '$lib/stores/billing'; + import { isOrganization, tierToPlan } from '$lib/stores/billing'; import { addNotification } from '$lib/stores/notifications'; import { organizationList, @@ -99,10 +99,6 @@ paymentMethodId = methods.paymentMethods.find((method) => !!method?.last4)?.$id ?? null; } - function isOrganization(org: Organization | OrganizationError): org is Organization { - return (org as Organization).$id !== undefined; - } - async function validate(organizationId: string, invites: string[]) { try { const org = await sdk.forConsole.billing.validateOrganization(organizationId, invites); diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index de8a9f63eb..8adad49999 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -30,7 +30,7 @@ WizardSecondaryFooter } from '$lib/layout'; import { type Coupon, type PaymentList } from '$lib/sdk/billing'; - import { plansInfo, tierToPlan, type Tier } from '$lib/stores/billing'; + import { isOrganization, plansInfo, tierToPlan, type Tier } from '$lib/stores/billing'; import { addNotification } from '$lib/stores/notifications'; import { currentPlan, @@ -182,10 +182,6 @@ } } - function isOrganization(org: Organization | OrganizationError): org is Organization { - return (org as Organization).$id !== undefined; - } - async function validate(organizationId: string, invites: string[]) { try { let org = await sdk.forConsole.billing.validateOrganization(organizationId, invites); From acb814b5ca9f7e956c8ff01eb7d8d88a4fccf45d Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 26 Jan 2025 06:44:37 +0000 Subject: [PATCH 066/231] fix function definiation --- .../settings/deleteOrganizationModal.svelte | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte b/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte index 96073a0460..28e43d5aae 100644 --- a/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte +++ b/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte @@ -100,8 +100,8 @@ organizationName = ''; } - let getEstimate = async () => { - if(isCloud) { + async function getEstimate() { + if (isCloud) { try { error = ''; estimation = await sdk.forConsole.billing.estimationDeleteOrganization( @@ -109,10 +109,9 @@ ); } catch (e) { error = e.message; - console.log(e); } } - }; + }
      @@ -124,7 +123,7 @@ icon="exclamation" state="warning" headerDivider={false}> - {#if estimation &&( estimation.unpaidInvoices.length > 0 || estimation.grossAmount > 0)} + {#if estimation && (estimation.unpaidInvoices.length > 0 || estimation.grossAmount > 0)} {:else}

      From dccfb2885a39e024ce368bbb3b9cdf7183cd0ca6 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 26 Jan 2025 06:55:39 +0000 Subject: [PATCH 067/231] fix new org error --- .../billing/+page.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/billing/+page.ts b/src/routes/(console)/organization-[organization]/billing/+page.ts index ef01264d7b..2bf2039c75 100644 --- a/src/routes/(console)/organization-[organization]/billing/+page.ts +++ b/src/routes/(console)/organization-[organization]/billing/+page.ts @@ -24,31 +24,36 @@ export const load: PageLoad = async ({ parent, depends }) => { .catch(() => null) : null; - const billingAggregationId = (organization as Organization)?.billingAggregationId; - + /** + * Needed to keep this out of Promise.all, as when organization is + * initially created, these might return 404 + * - can be removed later once that is fixed in back-end + */ let billingAggregation = null; try { - billingAggregation = await sdk.forConsole.billing.getAggregation(organization.$id, billingAggregationId); + billingAggregation = await sdk.forConsole.billing.getAggregation(organization.$id, (organization as Organization)?.billingAggregationId); } catch (e) { // ignore error } - const billingInvoiceId = (organization as Organization)?.billingInvoiceId; - + let billingInvoice = null; + try { + billingInvoice = await sdk.forConsole.billing.getInvoice(organization.$id, (organization as Organization)?.billingInvoiceId); + } catch (e) { + // ignore error + } const [ paymentMethods, addressList, billingAddress, creditList, - billingInvoice, aggregationBillingPlan, ] = await Promise.all([ sdk.forConsole.billing.listPaymentMethods(), sdk.forConsole.billing.listAddresses(), billingAddressPromise, sdk.forConsole.billing.listCredits(organization.$id), - sdk.forConsole.billing.getInvoice(organization.$id, billingInvoiceId), sdk.forConsole.billing.getPlan(billingAggregation?.plan ?? organization.billingPlan), ]); From 609cf5fe8b2475b55efa09694c6f7598b55ce5e2 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 26 Jan 2025 07:10:41 +0000 Subject: [PATCH 068/231] fix button state --- src/routes/(console)/create-organization/+page.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte index e84f8e1977..0edd44b728 100644 --- a/src/routes/(console)/create-organization/+page.svelte +++ b/src/routes/(console)/create-organization/+page.svelte @@ -63,6 +63,7 @@ let billingBudget: number; let showCreditModal = false; + let error = ''; onMount(async () => { if ($page.url.searchParams.has('coupon')) { @@ -237,6 +238,7 @@ {#if billingPlan !== BillingPlan.FREE} formComponent.triggerSubmit()} - disabled={$isSubmitting}> + disabled={$isSubmitting || error.length > 0}> Create organization From c97893932e704c0023af404c006688b450f6cd2e Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 26 Jan 2025 14:04:10 +0530 Subject: [PATCH 069/231] remove: custom id options when creating an organization. --- .../(console)/createOrganization.svelte | 23 +++-------------- src/routes/(console)/onboarding/+page.svelte | 25 ++----------------- 2 files changed, 5 insertions(+), 43 deletions(-) diff --git a/src/routes/(console)/createOrganization.svelte b/src/routes/(console)/createOrganization.svelte index 3c4d7b2194..6547a5c518 100644 --- a/src/routes/(console)/createOrganization.svelte +++ b/src/routes/(console)/createOrganization.svelte @@ -1,6 +1,5 @@

      {#if status} - + {/if}
      + + diff --git a/src/lib/layout/usageMultiple.svelte b/src/lib/layout/usageMultiple.svelte index 6e3d3be434..b12b0bc1ef 100644 --- a/src/lib/layout/usageMultiple.svelte +++ b/src/lib/layout/usageMultiple.svelte @@ -34,15 +34,13 @@
      {#if count} -
      -
      - ({ - name: legendData[index].name, - data: accumulateFromEndingTotal(c, total[index]) - }))} /> -
      +
      + ({ + name: legendData[index].name, + data: accumulateFromEndingTotal(c, total[index]) + }))} /> {#if legendData} @@ -53,11 +51,12 @@ diff --git a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte index b002e59f3c..a140f27b23 100644 --- a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte +++ b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte @@ -206,7 +206,7 @@

      {#if data.organizationUsage.databasesReads || data.organizationUsage.databasesWrites} -
      +
      {#if dbReads || dbWrites} -
      +
      Date: Mon, 27 Jan 2025 08:57:40 +0000 Subject: [PATCH 071/231] fix alert --- .../components/billing/estimatedTotal.svelte | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/lib/components/billing/estimatedTotal.svelte b/src/lib/components/billing/estimatedTotal.svelte index 0199e0ba96..5d2ab12b7d 100644 --- a/src/lib/components/billing/estimatedTotal.svelte +++ b/src/lib/components/billing/estimatedTotal.svelte @@ -21,12 +21,12 @@ async function getEstimate(billingPlan: string, collaborators: string[], couponId: string) { try { - error = ''; estimation = await sdk.forConsole.billing.estimationCreateOrganization( billingPlan, couponId === '' ? null : couponId, collaborators ?? [] ); + error = ''; } catch (e) { error = e.message; } @@ -56,15 +56,15 @@ : getEstimate(billingPlan, collaborators, couponId); -{#if error.length} - - - {error} - - -{:else if estimation} +{#if estimation || error.length} - + {#if error.length} +

      + {error} +

      + {/if} + + {#if estimation} {#each estimation.items ?? [] as item}

      {item.label}

      @@ -76,19 +76,18 @@ {/each}
      -

      - Total due -

      +

      Total due

      {formatCurrency(estimation.grossAmount)}

      - You'll pay {formatCurrency(estimation.grossAmount)} now. Once - your credits run out, you'll be charged + You'll pay {formatCurrency(estimation.grossAmount)} now. + Once your credits run out, you'll be charged {formatCurrency(estimation.grossAmount)} every 30 days.

      + {/if} Date: Mon, 27 Jan 2025 14:44:21 +0530 Subject: [PATCH 072/231] update: confirm leaving page if file upload in progress. --- .../storage/bucket-[bucket]/+page.svelte | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/routes/(console)/project-[project]/storage/bucket-[bucket]/+page.svelte b/src/routes/(console)/project-[project]/storage/bucket-[bucket]/+page.svelte index e9a7fc50b3..c25acc929d 100644 --- a/src/routes/(console)/project-[project]/storage/bucket-[bucket]/+page.svelte +++ b/src/routes/(console)/project-[project]/storage/bucket-[bucket]/+page.svelte @@ -50,6 +50,7 @@ import Create from './create-file/create.svelte'; import DeleteFile from './deleteFile.svelte'; import { isCloud } from '$lib/system'; + import { onMount } from 'svelte'; export let data; @@ -90,8 +91,31 @@ $: maxFileSize = isCloud ? humanFileSize(sizeToBytes(getServiceLimit('fileSize'), 'MB', 1000)) : null; + + let isUploading = false; + + const beforeunload = (event: BeforeUnloadEvent) => { + // legacy browser **may** support showing a custom message. + const message = 'An upload is in progress. Are you sure you want to leave?'; + + if (isUploading) { + event.preventDefault(); + event.returnValue = message; + return message; + } + }; + + onMount(() => { + return uploader.subscribe(() => { + isUploading = $uploader.files.some( + (file) => !file.completed && file.progress < 100 && !file.failed + ); + }); + }); + + From e358afc2fcb0a65443c625f1b472a1228bd2e3e3 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 27 Jan 2025 15:54:28 +0530 Subject: [PATCH 073/231] address comments: update copies, specs of the graphs. --- src/lib/layout/usageMultiple.svelte | 16 +++++++- .../usage/[[invoice]]/+page.svelte | 2 +- .../usage/[[period]]/+page.svelte | 38 ++++++++++--------- .../databases/usage/[[period]]/+page.svelte | 38 ++++++++++--------- 4 files changed, 57 insertions(+), 37 deletions(-) diff --git a/src/lib/layout/usageMultiple.svelte b/src/lib/layout/usageMultiple.svelte index b12b0bc1ef..aa9292c9c7 100644 --- a/src/lib/layout/usageMultiple.svelte +++ b/src/lib/layout/usageMultiple.svelte @@ -5,17 +5,23 @@ import { Card, Heading, SecondaryTabs, SecondaryTabsItem } from '$lib/components'; import { page } from '$app/stores'; import { type Models } from '@appwrite.io/console'; + import { formatNumberWithCommas } from '$lib/helpers/numbers'; export let title: string; export let total: number[]; export let path: string = null; export let count: Models.Metric[][]; export let legendData: LegendData[]; + export let showHeader: boolean = true; + export let overlapContainerCover = false; - +
      - {title} + {#if showHeader} + {title} + {/if} + {#if path} @@ -34,6 +40,12 @@
      {#if count} + {@const totalCount = total.reduce((a, b) => a + b, 0)} + + {formatNumberWithCommas(totalCount)} +

      Total {title.toLocaleLowerCase()}

      +
      +
      - Databases reads and writes + Database reads and writes

      The total number of database reads and writes across all projects in your organization. diff --git a/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte b/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte index fd5fd58755..56e0eb7220 100644 --- a/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte +++ b/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte @@ -17,21 +17,25 @@ $: writesTotal = data.databaseWritesTotal; - +

      + - + +
      diff --git a/src/routes/(console)/project-[project]/databases/usage/[[period]]/+page.svelte b/src/routes/(console)/project-[project]/databases/usage/[[period]]/+page.svelte index 334403f690..b4fbc25e73 100644 --- a/src/routes/(console)/project-[project]/databases/usage/[[period]]/+page.svelte +++ b/src/routes/(console)/project-[project]/databases/usage/[[period]]/+page.svelte @@ -16,21 +16,25 @@ $: writesTotal = data.databasesWritesTotal; - +
      + - + +
      From 303139dc56d08120520e30f2ef4a336aa6416e68 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 27 Jan 2025 19:18:41 +0530 Subject: [PATCH 074/231] address comments. --- src/lib/components/status.svelte | 1 - src/lib/layout/usageMultiple.svelte | 2 +- .../usage/[[invoice]]/+page.svelte | 2 +- .../database-[database]/usage/[[period]]/+page.svelte | 1 - .../project-[project]/databases/usage/[[period]]/+page.svelte | 1 - .../project-[project]/settings/usage/[[invoice]]/+page.svelte | 4 ---- 6 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/lib/components/status.svelte b/src/lib/components/status.svelte index 75fa4ad103..71ddbde695 100644 --- a/src/lib/components/status.svelte +++ b/src/lib/components/status.svelte @@ -36,6 +36,5 @@ .text { line-height: 140%; - letter-spacing: -0.063px; } diff --git a/src/lib/layout/usageMultiple.svelte b/src/lib/layout/usageMultiple.svelte index aa9292c9c7..81e9710b82 100644 --- a/src/lib/layout/usageMultiple.svelte +++ b/src/lib/layout/usageMultiple.svelte @@ -68,7 +68,7 @@ } :global(.multiple-chart-container .echart) { - margin-top: -1rem; + margin-top: -1em; margin-bottom: -1em; } diff --git a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte index 46fdce2a9b..d4b23112ab 100644 --- a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte +++ b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte @@ -138,7 +138,7 @@
      diff --git a/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte b/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte index 56e0eb7220..b094257acc 100644 --- a/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte +++ b/src/routes/(console)/project-[project]/databases/database-[database]/usage/[[period]]/+page.svelte @@ -9,7 +9,6 @@ $: total = data.collectionsTotal; $: count = data.collections; - // types need to be added to console sdk. $: reads = data.databaseReads; $: readsTotal = data.databaseReadsTotal; diff --git a/src/routes/(console)/project-[project]/databases/usage/[[period]]/+page.svelte b/src/routes/(console)/project-[project]/databases/usage/[[period]]/+page.svelte index b4fbc25e73..8c41fdc755 100644 --- a/src/routes/(console)/project-[project]/databases/usage/[[period]]/+page.svelte +++ b/src/routes/(console)/project-[project]/databases/usage/[[period]]/+page.svelte @@ -8,7 +8,6 @@ $: total = data.databasesTotal; $: count = data.databases; - // types need to be added to console sdk. $: reads = data.databasesReads; $: readsTotal = data.databasesReadsTotal; diff --git a/src/routes/(console)/project-[project]/settings/usage/[[invoice]]/+page.svelte b/src/routes/(console)/project-[project]/settings/usage/[[invoice]]/+page.svelte index 4412f6f923..a0d8c24109 100644 --- a/src/routes/(console)/project-[project]/settings/usage/[[invoice]]/+page.svelte +++ b/src/routes/(console)/project-[project]/settings/usage/[[invoice]]/+page.svelte @@ -37,12 +37,8 @@ data.usage.deploymentsStorageTotal + data.usage.buildsStorageTotal; - // types need to be added to console sdk. $: dbReads = data.usage.databasesReads; - $: dbReadsTotal = data.usage.databasesReadsTotal; - $: dbWrites = data.usage.databasesWrites; - $: dbWritesTotal = data.usage.databasesWritesTotal; $: legendData = [ { name: 'Reads', value: data.usage.databasesReadsTotal }, From d9fe601ca3678114ab9366802e90e9585d9913d6 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 28 Jan 2025 05:30:23 +0000 Subject: [PATCH 075/231] fix spacing --- src/lib/components/billing/discountsApplied.svelte | 3 +-- src/lib/components/billing/estimatedTotal.svelte | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/lib/components/billing/discountsApplied.svelte b/src/lib/components/billing/discountsApplied.svelte index 028854d277..d35b3a1680 100644 --- a/src/lib/components/billing/discountsApplied.svelte +++ b/src/lib/components/billing/discountsApplied.svelte @@ -1,5 +1,4 @@ {#if estimation || error.length} - + {#if error.length}

      {error} @@ -85,7 +85,7 @@

      You'll pay {formatCurrency(estimation.grossAmount)} now. Once your credits run out, you'll be charged - {formatCurrency(estimation.grossAmount)} every 30 days. + {formatCurrency(estimation.amount)} every 30 days.

      {/if} From 429c7da66fd8e822fbca8a6d5b75a7bf62c72dd5 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 28 Jan 2025 06:06:19 +0000 Subject: [PATCH 076/231] bring back credits modal --- .../billing/discountsApplied.svelte | 23 +++++++++ .../components/billing/estimatedTotal.svelte | 49 ++++++++++--------- src/lib/sdk/billing.ts | 3 +- .../change-plan/+page.svelte | 22 +++++---- 4 files changed, 64 insertions(+), 33 deletions(-) diff --git a/src/lib/components/billing/discountsApplied.svelte b/src/lib/components/billing/discountsApplied.svelte index d35b3a1680..82ae0907e6 100644 --- a/src/lib/components/billing/discountsApplied.svelte +++ b/src/lib/components/billing/discountsApplied.svelte @@ -1,8 +1,15 @@ {#if value > 0} @@ -14,6 +21,22 @@ {label}

      + {#if !fixedCoupon && label.toLowerCase() === 'credits'} + + {/if}
      {#if value >= 100}

      Credits applied

      diff --git a/src/lib/components/billing/estimatedTotal.svelte b/src/lib/components/billing/estimatedTotal.svelte index 3afd78945d..ce9a3558ca 100644 --- a/src/lib/components/billing/estimatedTotal.svelte +++ b/src/lib/components/billing/estimatedTotal.svelte @@ -1,7 +1,7 @@ - - - Users - - {@const sum = messageRecipients.length} - {#if sum} -
      - - - Name - Identifier - - - {#each messageRecipients.slice(offset, offset + limit) as recipient (recipient.$id)} - - -
      - - {recipient.name} - -
      -
      - - - {getIdentifier(recipient)} - - -
      - {/each} -
      -
      -
      -

      Total users: {messageRecipients.length}

      - -
      -
      - {:else} - -
      - No users have been selected. -

      - Need a hand? Check out our - - . -

      -
      -
      - {/if} -
      -
      diff --git a/src/routes/(console)/project-[project]/messaging/message-[message]/updateTargets.svelte b/src/routes/(console)/project-[project]/messaging/message-[message]/updateTargets.svelte index c05bdce614..a4ef930090 100644 --- a/src/routes/(console)/project-[project]/messaging/message-[message]/updateTargets.svelte +++ b/src/routes/(console)/project-[project]/messaging/message-[message]/updateTargets.svelte @@ -8,7 +8,14 @@ TableHeader, TableRow } from '$lib/elements/table'; - import { CardGrid, Heading, Empty, PaginationInline, EmptySearch } from '$lib/components'; + import { + CardGrid, + Heading, + Empty, + PaginationInline, + EmptySearch, + Alert + } from '$lib/components'; import { onMount } from 'svelte'; import { sdk } from '$lib/stores/sdk'; import { invalidate } from '$app/navigation'; @@ -22,6 +29,7 @@ export let message: Models.Message & { data: Record }; export let selectedTargetsById: Record; + export let selectedRecipients: Record>; let providerType: MessagingProviderType; let offset = 0; @@ -96,17 +104,74 @@ $: isDraft = message.status === 'draft'; $: disabled = symmetricDifference(targetIds, Object.keys(selectedTargetsById)).length === 0; + + $: recipients = message.users.reduce((acc, userId) => { + const recipient = selectedRecipients[userId]; + if (recipient) { + const target = recipient.targets.find((t) => t.providerType === message.providerType); + + if (target) { + acc[userId] = { + $id: recipient.$id, + name: recipient.name, + identifier: target.identifier, + providerType: message.providerType + }; + } + } else { + // user id exists but the user is null means the user account was deleted. + acc[userId] = null; + } + return acc; + }, {}); + + $: recipientsAvailable = recipientsCount > 0; + $: recipientsCount = Object.keys(recipients).filter((user) => user !== null).length; + $: hasDeletedUsers = Object.values(recipients).some((source) => source == null);
      Targets - {@const sum = targetIds.length} - {#if sum} + {@const sum = targetIds.length || Object.values(recipients).length} + {@const dataSource = + targets.length > 0 + ? targets + : Object.values(recipients).filter((user) => user !== null)} + + {#if hasDeletedUsers} +
      + {#if hasDeletedUsers && !dataSource.length} + + There are no targets to show + This message was sent to users who are no longer available, so their information + cannot be displayed. + + {:else} + 0} + on:dismiss={() => (hasDeletedUsers = false)}> + This message was sent to users who are no longer available, so their + information cannot be displayed. + + {/if} +
      + {/if} + + {#if sum && dataSource.length}
      -
      +
      Target + + {#if recipientsAvailable} + Identifier + + + + {/if}
      {#if isDraft}
      +
      - + + {#if recipientsAvailable} + + {/if} + + - {#each targets.slice(offset, offset + limit) as target (target.$id)} + + {#each dataSource.slice(offset, offset + limit) as source (source['$id'])}
      - {#if target.providerType === MessagingProviderType.Push} - {target.name} + {#if source['providerType'] === MessagingProviderType.Push} + {source['name']} {:else} - {target.identifier} + {source['identifier']} {/if}
      + {#if recipientsAvailable} + + + {source['name']} + + + {/if} + {#if isDraft}
      removeTarget(target.$id)}> + on:click={() => removeTarget(source['$id'])}>
      {:else if isDraft} (showTargets = true)}>Add a target - {:else} + {:else if !sum && !hasDeletedUsers}
      No targets have been selected. From 47d0b32ea8b042ec2373fbe99aad8189a94d2158 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 29 Jan 2025 03:26:09 +0000 Subject: [PATCH 081/231] review improvements --- .../components/billing/estimatedTotal.svelte | 39 ++++++++++++++----- src/lib/layout/wizardExitModal.svelte | 2 +- .../(console)/apply-credit/+page.svelte | 2 +- .../create-organization/+page.svelte | 26 ++++++------- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/src/lib/components/billing/estimatedTotal.svelte b/src/lib/components/billing/estimatedTotal.svelte index 210be56b6e..11eff6bf00 100644 --- a/src/lib/components/billing/estimatedTotal.svelte +++ b/src/lib/components/billing/estimatedTotal.svelte @@ -3,9 +3,11 @@ import { formatCurrency } from '$lib/helpers/numbers'; import type { Coupon, Estimation } from '$lib/sdk/billing'; import { sdk } from '$lib/stores/sdk'; + import { AppwriteException } from '@appwrite.io/console'; import Alert from '../alert.svelte'; import Card from '../card.svelte'; import DiscountsApplied from './discountsApplied.svelte'; + import { addNotification } from '$lib/stores/notifications'; export let organizationId: string | undefined = undefined; export let billingPlan: string; @@ -22,15 +24,30 @@ async function getEstimate(billingPlan: string, collaborators: string[], couponId: string) { try { - error = ''; estimation = await sdk.forConsole.billing.estimationCreateOrganization( billingPlan, couponId === '' ? null : couponId, collaborators ?? [] ); - error = estimation.error ?? ''; } catch (e) { - error = e.message; + if (e instanceof AppwriteException) { + if ( + e.type === 'coupon_not_found' || + e.type === 'coupon_already_used' || + e.type === 'billing_credits_unsupported' + ) { + couponData = { + code: null, + status: null, + credits: null + }; + } + } + addNotification({ + type: 'error', + isHtml: false, + message: e.message + }); } } @@ -41,16 +58,18 @@ couponId: string | undefined ) { try { - error = ''; estimation = await sdk.forConsole.billing.estimationUpdatePlan( organizationId, billingPlan, couponId && couponId.length > 0 ? couponId : null, collaborators ?? [] ); - error = estimation.error ?? ''; } catch (e) { - error = e.message; + addNotification({ + type: 'error', + isHtml: false, + message: e.message + }); } } @@ -70,10 +89,10 @@ {#if estimation} {#each estimation.items ?? [] as item} {#if item.value > 0} - -

      {item.label}

      -

      {formatCurrency(item.value)}

      -
      + +

      {item.label}

      +

      {formatCurrency(item.value)}

      +
      {/if} {/each} {#each estimation.discounts ?? [] as item} diff --git a/src/lib/layout/wizardExitModal.svelte b/src/lib/layout/wizardExitModal.svelte index 13f677e998..2b71f4a599 100644 --- a/src/lib/layout/wizardExitModal.svelte +++ b/src/lib/layout/wizardExitModal.svelte @@ -14,7 +14,7 @@ diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte index 0edd44b728..d3de145b89 100644 --- a/src/routes/(console)/create-organization/+page.svelte +++ b/src/routes/(console)/create-organization/+page.svelte @@ -3,13 +3,7 @@ import { base } from '$app/paths'; import { page } from '$app/stores'; import { Submit, trackError, trackEvent } from '$lib/actions/analytics'; - import { - PlanComparisonBox, - SelectPaymentMethod, - - SelectPlan - - } from '$lib/components/billing'; + import { PlanComparisonBox, SelectPaymentMethod, SelectPlan } from '$lib/components/billing'; import EstimatedTotal from '$lib/components/billing/estimatedTotal.svelte'; import ValidateCreditModal from '$lib/components/billing/validateCreditModal.svelte'; import Default from '$lib/components/roles/default.svelte'; @@ -227,23 +221,27 @@ id="members" /> - + {#if !couponData?.code} + + {/if} {/if} {#if billingPlan !== BillingPlan.FREE} + {couponData} /> {:else} {/if} From 269bf9f01e2ff0fa4d5ec51e8dfe4ca6d989c158 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 29 Jan 2025 04:05:33 +0000 Subject: [PATCH 082/231] fix formatting --- .../billing/discountsApplied.svelte | 2 +- .../components/billing/estimatedTotal.svelte | 24 +++++- src/lib/components/billing/index.ts | 2 +- src/lib/components/billing/selectPlan.svelte | 2 +- src/lib/sdk/billing.ts | 75 +++++++------------ src/lib/stores/billing.ts | 5 +- .../create-organization/+page.svelte | 2 - .../billing/+page.ts | 39 +++++----- .../billing/planSummary.svelte | 15 ++-- 9 files changed, 84 insertions(+), 82 deletions(-) diff --git a/src/lib/components/billing/discountsApplied.svelte b/src/lib/components/billing/discountsApplied.svelte index 82ae0907e6..433d02ecf0 100644 --- a/src/lib/components/billing/discountsApplied.svelte +++ b/src/lib/components/billing/discountsApplied.svelte @@ -1,6 +1,6 @@ {#if estimation || error.length} diff --git a/src/lib/components/billing/index.ts b/src/lib/components/billing/index.ts index f58efa2504..1cc70d3d99 100644 --- a/src/lib/components/billing/index.ts +++ b/src/lib/components/billing/index.ts @@ -7,4 +7,4 @@ export { default as EmptyCardCloud } from './emptyCardCloud.svelte'; export { default as CreditsApplied } from './creditsApplied.svelte'; export { default as PlanSelection } from './planSelection.svelte'; export { default as EstimatedTotal } from './estimatedTotal.svelte'; -export { default as SelectPlan } from './selectPlan.svelte'; \ No newline at end of file +export { default as SelectPlan } from './selectPlan.svelte'; diff --git a/src/lib/components/billing/selectPlan.svelte b/src/lib/components/billing/selectPlan.svelte index 4447c17e3f..8aae2f0acc 100644 --- a/src/lib/components/billing/selectPlan.svelte +++ b/src/lib/components/billing/selectPlan.svelte @@ -19,7 +19,7 @@ = [], + invites: Array = [] ): Promise { const path = `/organizations/estimations/create-organization`; const params = { billingPlan, couponId, - invites, + invites }; const uri = new URL(this.client.config.endpoint + path); return await this.client.call( @@ -466,40 +465,30 @@ export class Billing { ); } - async estimationDeleteOrganization(organizationId: string): Promise { + async estimationDeleteOrganization( + organizationId: string + ): Promise { const path = `/organizations/${organizationId}/estimations/delete-organization`; const uri = new URL(this.client.config.endpoint + path); - return await this.client.call( - 'patch', - uri, - { - 'content-type': 'application/json' - } - ); + return await this.client.call('patch', uri, { + 'content-type': 'application/json' + }); } async getOrganizationPlan(organizationId: string): Promise { const path = `/organizations/${organizationId}/plan`; const uri = new URL(this.client.config.endpoint + path); - return await this.client.call( - 'get', - uri, - { - 'content-type': 'application/json' - } - ); + return await this.client.call('get', uri, { + 'content-type': 'application/json' + }); } async getPlan(planId: string): Promise { const path = `/console/plans/${planId}`; const uri = new URL(this.client.config.endpoint + path); - return await this.client.call( - 'get', - uri, - { - 'content-type': 'application/json' - } - ); + return await this.client.call('get', uri, { + 'content-type': 'application/json' + }); } async getRoles(organizationId: string): Promise { @@ -546,13 +535,13 @@ export class Billing { organizationId: string, billingPlan: string, couponId: string = null, - invites: Array = [], + invites: Array = [] ): Promise { const path = `/organizations/${organizationId}/estimations/update-plan`; const params = { billingPlan, couponId, - invites, + invites }; const uri = new URL(this.client.config.endpoint + path); return await this.client.call( @@ -565,18 +554,12 @@ export class Billing { ); } - async cancelDowngrade( - organizationId: string - ): Promise { + async cancelDowngrade(organizationId: string): Promise { const path = `/organizations/${organizationId}/plan/cancel`; const uri = new URL(this.client.config.endpoint + path); - return await this.client.call( - 'patch', - uri, - { - 'content-type': 'application/json' - } - ); + return await this.client.call('patch', uri, { + 'content-type': 'application/json' + }); } async updateBudget( diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index 341e302bb3..d4affddb60 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -275,7 +275,8 @@ export async function checkForUsageLimit(org: Organization) { const members = org.total; const plan = get(plansInfo)?.get(org.billingPlan); - const membersOverflow = (members - 1) > plan.addons.seats.limit ? members - (plan.addons.seats.limit || members) : 0; + const membersOverflow = + members - 1 > plan.addons.seats.limit ? members - (plan.addons.seats.limit || members) : 0; if (resources.some((r) => r.value >= 100) || membersOverflow > 0) { readOnly.set(true); @@ -490,4 +491,4 @@ export function calculateResourceSurplus(total: number, limit: number, limitUnit export function isOrganization(org: Organization | OrganizationError): org is Organization { return (org as Organization).$id !== undefined; -} \ No newline at end of file +} diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte index d3de145b89..9137dc1284 100644 --- a/src/routes/(console)/create-organization/+page.svelte +++ b/src/routes/(console)/create-organization/+page.svelte @@ -47,7 +47,6 @@ let billingPlan: BillingPlan = BillingPlan.FREE; let paymentMethodId: string; let collaborators: string[] = []; - let couponId: string | undefined; let couponData: Partial = { code: null, status: null, @@ -240,7 +239,6 @@ {billingBudget} {billingPlan} {collaborators} - {couponId} {couponData} /> {:else} diff --git a/src/routes/(console)/organization-[organization]/billing/+page.ts b/src/routes/(console)/organization-[organization]/billing/+page.ts index 2bf2039c75..b72e98ea0c 100644 --- a/src/routes/(console)/organization-[organization]/billing/+page.ts +++ b/src/routes/(console)/organization-[organization]/billing/+page.ts @@ -20,42 +20,43 @@ export const load: PageLoad = async ({ parent, depends }) => { const billingAddressId = (organization as Organization)?.billingAddressId; const billingAddressPromise: Promise
      = billingAddressId ? sdk.forConsole.billing - .getOrganizationBillingAddress(organization.$id, billingAddressId) - .catch(() => null) + .getOrganizationBillingAddress(organization.$id, billingAddressId) + .catch(() => null) : null; /** - * Needed to keep this out of Promise.all, as when organization is + * Needed to keep this out of Promise.all, as when organization is * initially created, these might return 404 * - can be removed later once that is fixed in back-end */ let billingAggregation = null; try { - billingAggregation = await sdk.forConsole.billing.getAggregation(organization.$id, (organization as Organization)?.billingAggregationId); + billingAggregation = await sdk.forConsole.billing.getAggregation( + organization.$id, + (organization as Organization)?.billingAggregationId + ); } catch (e) { // ignore error } - + let billingInvoice = null; try { - billingInvoice = await sdk.forConsole.billing.getInvoice(organization.$id, (organization as Organization)?.billingInvoiceId); + billingInvoice = await sdk.forConsole.billing.getInvoice( + organization.$id, + (organization as Organization)?.billingInvoiceId + ); } catch (e) { // ignore error } - const [ - paymentMethods, - addressList, - billingAddress, - creditList, - aggregationBillingPlan, - ] = await Promise.all([ - sdk.forConsole.billing.listPaymentMethods(), - sdk.forConsole.billing.listAddresses(), - billingAddressPromise, - sdk.forConsole.billing.listCredits(organization.$id), - sdk.forConsole.billing.getPlan(billingAggregation?.plan ?? organization.billingPlan), - ]); + const [paymentMethods, addressList, billingAddress, creditList, aggregationBillingPlan] = + await Promise.all([ + sdk.forConsole.billing.listPaymentMethods(), + sdk.forConsole.billing.listAddresses(), + billingAddressPromise, + sdk.forConsole.billing.listCredits(organization.$id), + sdk.forConsole.billing.getPlan(billingAggregation?.plan ?? organization.billingPlan) + ]); return { paymentMethods, diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte index f88992b861..8cfaeee8c8 100644 --- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte +++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte @@ -18,7 +18,7 @@ export let currentPlan: Plan; export let creditList: CreditList; export let currentInvoice: Invoice | undefined = undefined; - export let currentAggregation: Aggregation | undefined = undefined + export let currentAggregation: Aggregation | undefined = undefined; let showCancel: boolean = false; @@ -46,8 +46,7 @@
      - - {tierToPlan($organization?.billingPlan)?.name} plan + {currentPlan.name} plan
      {isTrial || $organization?.billingPlan === BillingPlan.GITHUB_EDUCATION @@ -63,7 +62,9 @@ Add-ons{currentAggregation.additionalMembers > 0 ? currentInvoice.usage.length + 1 : currentInvoice.usage.length} + >{currentAggregation.additionalMembers > 0 + ? currentInvoice.usage.length + 1 + : currentInvoice.usage.length}
      @@ -100,10 +101,12 @@ {#if currentInvoice?.usage} {#each currentInvoice.usage as excess, i}
    • + 0 ? 'u-padding-block-8' : 'u-padding-block-start-8'}" - class:u-sep-block-start={i > 0 || currentAggregation.additionalMembers > 0}> + class:u-sep-block-start={i > 0 || + currentAggregation.additionalMembers > 0}> {#if ['storage', 'bandwidth'].includes(excess.name)} {@const excessValue = humanFileSize( excess.value From 079b7b572a568c1a2683cc4f4cf77aa444bf86a6 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 29 Jan 2025 04:20:04 +0000 Subject: [PATCH 083/231] fix refactor --- .../components/billing/estimatedTotal.svelte | 11 ++------- .../(console)/apply-credit/+page.svelte | 2 +- .../create-organization/+page.svelte | 24 +++++++++++-------- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/lib/components/billing/estimatedTotal.svelte b/src/lib/components/billing/estimatedTotal.svelte index b16893a246..1884cc2e8c 100644 --- a/src/lib/components/billing/estimatedTotal.svelte +++ b/src/lib/components/billing/estimatedTotal.svelte @@ -4,7 +4,6 @@ import type { Coupon, Estimation } from '$lib/sdk/billing'; import { sdk } from '$lib/stores/sdk'; import { AppwriteException } from '@appwrite.io/console'; - import Alert from '../alert.svelte'; import Card from '../card.svelte'; import DiscountsApplied from './discountsApplied.svelte'; import { addNotification } from '$lib/stores/notifications'; @@ -13,7 +12,6 @@ export let billingPlan: string; export let collaborators: string[]; export let fixedCoupon = false; - export let error = ''; export let couponData: Partial; export let billingBudget: number; @@ -94,14 +92,9 @@ : getEstimate(billingPlan, collaborators, couponData?.code); -{#if estimation || error.length} +{#if estimation} - {#if error.length} - - {error} - - {/if} - + {#if estimation} {#each estimation.items ?? [] as item} {#if item.value > 0} diff --git a/src/routes/(console)/apply-credit/+page.svelte b/src/routes/(console)/apply-credit/+page.svelte index 9b1b3731e7..ced29eda1f 100644 --- a/src/routes/(console)/apply-credit/+page.svelte +++ b/src/routes/(console)/apply-credit/+page.svelte @@ -291,7 +291,7 @@ organizationId={selectedOrgId === newOrgId ? undefined : selectedOrgId} {billingPlan} {collaborators} - couponId={couponData.code}> + {couponData}> {#if campaign?.template === 'review' && (campaign?.cta || campaign?.claimed || campaign?.unclaimed)}

      {campaign?.cta}

      diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte index 9137dc1284..622ea0129a 100644 --- a/src/routes/(console)/create-organization/+page.svelte +++ b/src/routes/(console)/create-organization/+page.svelte @@ -56,11 +56,20 @@ let billingBudget: number; let showCreditModal = false; - let error = ''; onMount(async () => { if ($page.url.searchParams.has('coupon')) { - couponId = $page.url.searchParams.get('coupon'); + const coupon = $page.url.searchParams.get('coupon'); + try { + const response = await sdk.forConsole.billing.getCoupon(coupon); + couponData = response; + } catch (e) { + couponData = { + code: null, + status: null, + credits: null + }; + } } if ($page.url.searchParams.has('name')) { name = $page.url.searchParams.get('name'); @@ -132,7 +141,7 @@ billingPlan, paymentMethodId, null, - couponId && couponId.length > 0 ? couponId : null, + couponData.code ? couponData.code : null, collaborators, billingBudget, taxId @@ -234,12 +243,7 @@ {#if billingPlan !== BillingPlan.FREE} - + {:else} {/if} @@ -251,7 +255,7 @@ From 3c373367fba86f520ba8ccf1866d6a6c76510540 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 29 Jan 2025 04:27:52 +0000 Subject: [PATCH 084/231] remove unused code --- .../organization-[organization]/change-plan/+page.svelte | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index 6d51e61b24..fc6a14f542 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -18,7 +18,6 @@ FormList, InputSelect, InputTags, - InputText, InputTextarea, Label } from '$lib/elements/forms'; @@ -274,7 +273,7 @@ $: if (billingPlan !== BillingPlan.FREE) { loadPaymentMethods(); } - $: isButtonDisabled = $organization.billingPlan === billingPlan || error.length > 0; + $: isButtonDisabled = $organization.billingPlan === billingPlan; @@ -389,7 +388,7 @@ From 65720b25b9c3170eff910ef7e4a3ffce956451f6 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Wed, 29 Jan 2025 04:41:52 +0000 Subject: [PATCH 085/231] improve delete organization --- src/lib/stores/billing.ts | 4 + .../deleteOrganizationEstimation.svelte | 18 +--- .../settings/deleteOrganizationModal.svelte | 18 ++-- .../settings/invoicesTable.svelte | 93 ++++++++++--------- 4 files changed, 68 insertions(+), 65 deletions(-) diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index d4affddb60..455c1e1399 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -469,6 +469,10 @@ export const upgradeURL = derived( page, ($page) => `${base}/organization-${$page.data?.organization?.$id}/change-plan` ); +export const billingURL = derived( + page, + ($page) => `${base}/organization-${$page.data?.organization?.$id}/billing` +); export const hideBillingHeaderRoutes = ['/console/create-organization', '/console/account']; diff --git a/src/routes/(console)/organization-[organization]/settings/deleteOrganizationEstimation.svelte b/src/routes/(console)/organization-[organization]/settings/deleteOrganizationEstimation.svelte index 3d6a967b9d..df79ddae53 100644 --- a/src/routes/(console)/organization-[organization]/settings/deleteOrganizationEstimation.svelte +++ b/src/routes/(console)/organization-[organization]/settings/deleteOrganizationEstimation.svelte @@ -1,31 +1,19 @@ -{#if error} - - {error} - -{/if} {#if estimation} {#if estimation.unpaidInvoices?.length > 0} - You have a unpaid invoices. Please settle them first in order to delete team. + This organization has unresolved invoices that must be settled before it can be + deleted. Please review and resolve these invoices to proceed. - + {/if} {/if} - -{#if $selectedInvoice} - -{/if} diff --git a/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte b/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte index 28e43d5aae..b3c7c51e0d 100644 --- a/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte +++ b/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte @@ -22,6 +22,7 @@ } from '$lib/elements/table'; import { onMount } from 'svelte'; import DeleteOrganizationEstimation from './deleteOrganizationEstimation.svelte'; + import { billingURL } from '$lib/stores/billing'; export let showDelete = false; export let invoices: InvoiceList; @@ -215,12 +216,17 @@ - + {#if estimation && estimation.unpaidInvoices.length > 0} + + {:else} + + {/if}
      diff --git a/src/routes/(console)/organization-[organization]/settings/invoicesTable.svelte b/src/routes/(console)/organization-[organization]/settings/invoicesTable.svelte index fccee4c6a2..cbf881c3f9 100644 --- a/src/routes/(console)/organization-[organization]/settings/invoicesTable.svelte +++ b/src/routes/(console)/organization-[organization]/settings/invoicesTable.svelte @@ -23,6 +23,7 @@ const endpoint = getApiEndpoint(); export let invoices: Invoice[]; + export let showActions = true; function retryPayment(invoice: Invoice) { $selectedInvoice = invoice; @@ -35,7 +36,9 @@ Due Date Status Amount Due - + {#if showActions} + + {/if} {#each invoices as invoice, i} @@ -84,53 +87,55 @@ {formatCurrency(invoice.grossAmount)} - - - - - (showDropdown[i] = !showDropdown[i])} - event="view_invoice"> - View invoice - - + + + + (showDropdown[i] = !showDropdown[i])} + event="view_invoice"> + View invoice + + { - retryPayment(invoice); showDropdown[i] = !showDropdown[i]; - trackEvent(`click_retry_payment`, { - from: 'button', - source: 'billing_invoice_menu' - }); - }}> - Retry payment - - {/if} - - - + }} + event="download_invoice"> + Download PDF + + {#if status === 'overdue' || status === 'failed'} + { + retryPayment(invoice); + showDropdown[i] = !showDropdown[i]; + trackEvent(`click_retry_payment`, { + from: 'button', + source: 'billing_invoice_menu' + }); + }}> + Retry payment + + {/if} + + + + {/if} {/each} From f3c903a3085e083e737bd2b854bb21c2074b9977 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 29 Jan 2025 10:47:02 +0530 Subject: [PATCH 086/231] bump: console sdk for db read/writes. --- package.json | 2 +- pnpm-lock.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 428927dc57..348f13dbee 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "e2e:ui": "playwright test tests/e2e --ui" }, "dependencies": { - "@appwrite.io/console": "1.4.7", + "@appwrite.io/console": "1.5.1", "@appwrite.io/pink": "0.25.0", "@appwrite.io/pink-icons": "0.25.0", "@popperjs/core": "^2.11.8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a31a13a9ef..911bb0c01e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@appwrite.io/console': - specifier: 1.4.7 - version: 1.4.7 + specifier: 1.5.1 + version: 1.5.1 '@appwrite.io/pink': specifier: 0.25.0 version: 0.25.0 @@ -199,8 +199,8 @@ packages: '@analytics/type-utils@0.6.2': resolution: {integrity: sha512-TD+xbmsBLyYy/IxFimW/YL/9L2IEnM7/EoV9Aeh56U64Ify8o27HJcKjo38XY9Tcn0uOq1AX3thkKgvtWvwFQg==} - '@appwrite.io/console@1.4.7': - resolution: {integrity: sha512-5zx+c5nWRm/UJNxgtOi4vj1pYW+wusfnOX2hqEGDLLuNZRc1rViYRefNuezosp5SPtjClCIYn9TGuFlz/XLwhw==} + '@appwrite.io/console@1.5.1': + resolution: {integrity: sha512-H0fkBprsxXjOhbrE+MqXt1e4Gx4QeRdHuvMs7UxqGr2fAVEqh4ez2yk40A0ZSQvvN+rqLduoItMHQFl+sCPbtQ==} '@appwrite.io/pink-icons@0.25.0': resolution: {integrity: sha512-0O3i2oEuh5mWvjO80i+X6rbzrWLJ1m5wmv2/M3a1p2PyBJsFxN8xQMTEmTn3Wl/D26SsM7SpzbdW6gmfgoVU9Q==} @@ -3834,7 +3834,7 @@ snapshots: '@analytics/type-utils@0.6.2': {} - '@appwrite.io/console@1.4.7': {} + '@appwrite.io/console@1.5.1': {} '@appwrite.io/pink-icons@0.25.0': {} From bb04620771eee3fcb232b1887b5727c654b83f29 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 29 Jan 2025 10:48:41 +0530 Subject: [PATCH 087/231] fix: svelte check. --- src/lib/components/status.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/status.svelte b/src/lib/components/status.svelte index 71ddbde695..7dc78c84ec 100644 --- a/src/lib/components/status.svelte +++ b/src/lib/components/status.svelte @@ -9,7 +9,7 @@ | 'building' | 'none'; - export let statusIconStyle: string; + export let statusIconStyle: string | undefined = undefined;
      Date: Wed, 29 Jan 2025 12:29:08 +0530 Subject: [PATCH 088/231] update: safeguard when the backend may not yet support the metrics for db read/writes. --- src/lib/layout/usage.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/layout/usage.svelte b/src/lib/layout/usage.svelte index 8f392847f8..d9f31bc11b 100644 --- a/src/lib/layout/usage.svelte +++ b/src/lib/layout/usage.svelte @@ -43,7 +43,7 @@ metrics: Models.Metric[], endingTotal: number ): Array<[string, number]> { - return metrics.reduceRight( + return (metrics ?? []).reduceRight( (acc, curr) => { acc.data.unshift([curr.date, acc.total]); acc.total -= curr.value; From 242c9bd6015e69c856b8167e9d00ea9c6837c550 Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 29 Jan 2025 16:06:41 +0530 Subject: [PATCH 089/231] update: allow focus on labels to trigger enter hit. --- src/lib/components/regionCard.svelte | 12 ++++++++++++ .../organization-[organization]/wizard/step2.svelte | 6 ++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/lib/components/regionCard.svelte b/src/lib/components/regionCard.svelte index 3e1964802b..795451e46b 100644 --- a/src/lib/components/regionCard.svelte +++ b/src/lib/components/regionCard.svelte @@ -1,9 +1,12 @@