From 9294b7f6ed23e07262600958961e89e7319c8049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 23 Jun 2025 10:43:54 +0200 Subject: [PATCH 1/6] Fix manual deployment flows (missing file, domain configuration) --- .../domain-[domain]/importRecordModal.svelte | 2 +- .../create-function/manual/+page.svelte | 2 +- .../(modals)/createManual.svelte | 2 +- .../providers/settingsFormInput.svelte | 2 +- .../sites/create-site/manual/+page.svelte | 29 +++++++++---------- .../sites/create-site/manual/+page.ts | 13 ++++++++- .../sites/create-site/store.ts | 9 ++++-- .../createManualDeploymentModal.svelte | 2 +- .../bucket-[bucket]/create/+page.svelte | 2 +- 9 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/domains/domain-[domain]/importRecordModal.svelte b/src/routes/(console)/organization-[organization]/domains/domain-[domain]/importRecordModal.svelte index 5d0eeda5a..53df79780 100644 --- a/src/routes/(console)/organization-[organization]/domains/domain-[domain]/importRecordModal.svelte +++ b/src/routes/(console)/organization-[organization]/domains/domain-[domain]/importRecordModal.svelte @@ -37,7 +37,7 @@ } function handleInvalid(e: CustomEvent) { - const reason = e.detail.reason; + const reason = e.detail?.reason ?? ''; if (reason === InvalidFileType.EXTENSION) { error = 'Only .txt files allowed'; } else if (reason === InvalidFileType.SIZE) { diff --git a/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte index bd7f4106b..7650055ef 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/create-function/manual/+page.svelte @@ -130,7 +130,7 @@ } function handleInvalid(e: CustomEvent) { - const reason = e.detail.reason; + const reason = e.detail?.reason ?? ''; if (reason === InvalidFileType.EXTENSION) { addNotification({ type: 'error', diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte index 6259d577c..bd063bdfd 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createManual.svelte @@ -48,7 +48,7 @@ } function handleInvalid(e: CustomEvent) { - const reason = e.detail.reason; + const reason = e.detail?.reason ?? ''; if (reason === InvalidFileType.EXTENSION) { error = 'Only .tar.gz files allowed'; } else if (reason === InvalidFileType.SIZE) { diff --git a/src/routes/(console)/project-[region]-[project]/messaging/providers/settingsFormInput.svelte b/src/routes/(console)/project-[region]-[project]/messaging/providers/settingsFormInput.svelte index 35ba274ba..411420a6b 100644 --- a/src/routes/(console)/project-[region]-[project]/messaging/providers/settingsFormInput.svelte +++ b/src/routes/(console)/project-[region]-[project]/messaging/providers/settingsFormInput.svelte @@ -58,7 +58,7 @@ } function handleInvalid(e: CustomEvent) { - const reason = e.detail.reason; + const reason = e.detail?.reason ?? ''; if (reason === InvalidFileType.EXTENSION) { addNotification({ diff --git a/src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.svelte index 0d9f1b58b..0d46fcadd 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.svelte @@ -14,17 +14,13 @@ import { BuildRuntime, Framework, ID } from '@appwrite.io/console'; import type { Models } from '@appwrite.io/console'; import Configuration from '../configuration.svelte'; - import { buildVerboseDomain } from '../store'; - import { - project, - regionalConsoleVariables - } from '$routes/(console)/project-[region]-[project]/store'; - import { organization } from '$lib/stores/organization'; + import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; import { IconInfo } from '@appwrite.io/pink-icons-svelte'; import { InvalidFileType, removeFile } from '$lib/helpers/files'; import { humanFileSize } from '$lib/helpers/sizeConvertion'; import { isCloud } from '$lib/system'; import { currentPlan } from '$lib/stores/organization'; + import Domain from '../domain.svelte'; export let data; let showExitModal = false; @@ -34,7 +30,8 @@ let name = 'My website'; let id = ID.unique(); - let domain = `${id}.${$regionalConsoleVariables._APP_DOMAIN_SITES}`; + let domain = data.domain; + let domainIsValid = true; let framework: Models.Framework = data.frameworks.frameworks?.find((f) => f.key === 'other') ?? data.frameworks.frameworks?.[0]; @@ -54,13 +51,13 @@ async function create() { try { - domain = await buildVerboseDomain( - $regionalConsoleVariables._APP_DOMAIN_SITES, - name, - $organization.name, - $project.name, - id - ); + if (!domainIsValid) { + addNotification({ + type: 'error', + message: 'Domain is not valid' + }); + return; + } const fr = Object.values(Framework).find((f) => f === framework.key); const buildRuntime = Object.values(BuildRuntime).find( @@ -138,7 +135,7 @@ } function handleInvalid(e: CustomEvent) { - const reason = e.detail.reason; + const reason = e.detail?.reason ?? ''; if (reason === InvalidFileType.EXTENSION) { addNotification({ type: 'error', @@ -233,6 +230,8 @@ bind:selectedFramework={framework} bind:variables frameworks={data.frameworks.frameworks} /> + + diff --git a/src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.ts b/src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.ts index 0d16bd7bb..584877a05 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.ts +++ b/src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.ts @@ -1,9 +1,20 @@ import { sdk } from '$lib/stores/sdk'; +import { ID } from '@appwrite.io/console'; +import { buildVerboseDomain } from '../store'; export const load = async ({ parent, params }) => { - const { frameworks } = await parent(); + const { frameworks, project, organization, regionalConsoleVariables } = await parent(); + + const domain = await buildVerboseDomain( + regionalConsoleVariables._APP_DOMAIN_SITES, + '', // name + organization.name, + project.name, + ID.unique() + ); return { + domain, frameworks, template: await sdk .forProject(params.region, params.project) diff --git a/src/routes/(console)/project-[region]-[project]/sites/create-site/store.ts b/src/routes/(console)/project-[region]-[project]/sites/create-site/store.ts index 9f866d869..565925eb2 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/create-site/store.ts +++ b/src/routes/(console)/project-[region]-[project]/sites/create-site/store.ts @@ -28,10 +28,15 @@ export async function buildVerboseDomain( : ''; const safeUnique = unique ? toURLSafe(unique).toLowerCase() : ID.unique(); let domain = `${safeName}`; - if (await checkDomain(domain, apex)) { + if (domain && (await checkDomain(domain, apex))) { return domain; } - domain += '-' + safeSpecifier; + + if (domain) { + domain += '-'; + } + + domain += safeSpecifier; if (await checkDomain(domain, apex)) { return domain; } diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/createManualDeploymentModal.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/createManualDeploymentModal.svelte index 3930d56c7..a428f7cc9 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/createManualDeploymentModal.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/createManualDeploymentModal.svelte @@ -42,7 +42,7 @@ } function handleInvalid(e: CustomEvent) { - const reason = e.detail.reason; + const reason = e.detail?.reason ?? ''; if (reason === InvalidFileType.EXTENSION) { error = 'Only .tar.gz files allowed'; } else if (reason === InvalidFileType.SIZE) { diff --git a/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/create/+page.svelte b/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/create/+page.svelte index 0e4b0a97f..3bb100c47 100644 --- a/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/create/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/create/+page.svelte @@ -76,7 +76,7 @@ } function handleInvalid(e: CustomEvent) { - const reason = e.detail.reason; + const reason = e.detail?.reason ?? ''; if (reason === InvalidFileType.EXTENSION) { addNotification({ type: 'error', From f3e69a67e44dcf400daf38af889ad2064dde848d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 23 Jun 2025 11:32:49 +0200 Subject: [PATCH 2/6] Code quality improvement --- .../sites/create-site/manual/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.svelte index 0d46fcadd..b3a8b8a16 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/create-site/manual/+page.svelte @@ -14,7 +14,7 @@ import { BuildRuntime, Framework, ID } from '@appwrite.io/console'; import type { Models } from '@appwrite.io/console'; import Configuration from '../configuration.svelte'; - import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; + import { regionalConsoleVariables } from '../../../store'; import { IconInfo } from '@appwrite.io/pink-icons-svelte'; import { InvalidFileType, removeFile } from '$lib/helpers/files'; import { humanFileSize } from '$lib/helpers/sizeConvertion'; From b40dc74243705669e5430dea8688cd6cb6e5b3a4 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 24 Jun 2025 09:12:57 +0530 Subject: [PATCH 3/6] chore: record more info in billing feedback --- .../organization-[organization]/change-plan/+page.svelte | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index fa34d608e..1a497f7ac 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -33,7 +33,7 @@ import { onMount } from 'svelte'; import { loadAvailableRegions } from '$routes/(console)/regions'; import EstimatedTotalBox from '$lib/components/billing/estimatedTotalBox.svelte'; - + import { Query } from '@appwrite.io/console'; export let data; let selectedCoupon: Partial = null; @@ -114,6 +114,10 @@ null ); + const paidInvoices = await sdk.forConsole.billing.listInvoices(data.organization.$id, [ + Query.equal('status', 'succeeded') + ]); + await fetch(`${VARS.GROWTH_ENDPOINT}/feedback/billing`, { method: 'POST', headers: { @@ -128,6 +132,9 @@ )?.label, orgId: data.organization.$id, userId: data.account.$id, + orgAge: data.organization.$createdAt, + userAge: data.account.$createdAt, + paidInvoices: paidInvoices.total, message: feedbackMessage ?? '' }) }); From 9ac21e90a36f2d6969a5f8e6e00e743ecf10ab94 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 24 Jun 2025 09:13:33 +0530 Subject: [PATCH 4/6] chore: format --- .../organization-[organization]/change-plan/+page.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index 1a497f7ac..c331ab0f3 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -34,6 +34,7 @@ import { loadAvailableRegions } from '$routes/(console)/regions'; import EstimatedTotalBox from '$lib/components/billing/estimatedTotalBox.svelte'; import { Query } from '@appwrite.io/console'; + export let data; let selectedCoupon: Partial = null; From 5d9f1fcb6df3ae6d2a56c365ec3541ccf9e31bc0 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 24 Jun 2025 10:08:48 +0530 Subject: [PATCH 5/6] refactor: extract downgrade feedback logic into a separate function --- .../change-plan/+page.svelte | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index c331ab0f3..09065a70c 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -106,6 +106,33 @@ } } + async function trackDowngradeFeedback() { + const paidInvoices = await sdk.forConsole.billing.listInvoices(data.organization.$id, [ + Query.equal('status', 'succeeded') + ]); + + await fetch(`${VARS.GROWTH_ENDPOINT}/feedback/billing`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + from: tierToPlan(data.organization.billingPlan).name, + to: tierToPlan(selectedPlan).name, + email: data.account.email, + reason: feedbackDowngradeOptions.find( + (option) => option.value === feedbackDowngradeReason + )?.label, + orgId: data.organization.$id, + userId: data.account.$id, + orgAge: data.organization.$createdAt, + userAge: data.account.$createdAt, + paidInvoices: paidInvoices.total, + message: feedbackMessage ?? '' + }) + }); + } + async function downgrade() { try { await sdk.forConsole.billing.updatePlan( @@ -115,30 +142,7 @@ null ); - const paidInvoices = await sdk.forConsole.billing.listInvoices(data.organization.$id, [ - Query.equal('status', 'succeeded') - ]); - - await fetch(`${VARS.GROWTH_ENDPOINT}/feedback/billing`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - from: tierToPlan(data.organization.billingPlan).name, - to: tierToPlan(selectedPlan).name, - email: data.account.email, - reason: feedbackDowngradeOptions.find( - (option) => option.value === feedbackDowngradeReason - )?.label, - orgId: data.organization.$id, - userId: data.account.$id, - orgAge: data.organization.$createdAt, - userAge: data.account.$createdAt, - paidInvoices: paidInvoices.total, - message: feedbackMessage ?? '' - }) - }); + trackDowngradeFeedback(); await invalidate(Dependencies.ORGANIZATION); From 2e55b3cc939829aa871025770d598c85f1e48f5e Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 24 Jun 2025 10:09:44 +0530 Subject: [PATCH 6/6] chore: track only non credit invoices --- .../organization-[organization]/change-plan/+page.svelte | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index 09065a70c..f31095d81 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -108,7 +108,8 @@ async function trackDowngradeFeedback() { const paidInvoices = await sdk.forConsole.billing.listInvoices(data.organization.$id, [ - Query.equal('status', 'succeeded') + Query.equal('status', 'succeeded'), + Query.greaterThan('grossAmount', 0) ]); await fetch(`${VARS.GROWTH_ENDPOINT}/feedback/billing`, {