fix: delete flow, upgrade flow, QA

This commit is contained in:
Arman
2023-11-27 22:05:50 +01:00
parent fc137fecc5
commit 3452f3b1b6
12 changed files with 73 additions and 28 deletions
+1 -1
View File
@@ -115,7 +115,7 @@
<div class="main-header-end">
<nav class="u-flex is-only-desktop u-cross-center">
{#if isCloud && $organization?.billingPlan !== 'tier-2' && !$page.url.pathname.startsWith('/console/account')}
{#if isCloud && $organization?.billingPlan === 'tier-0' && !$page.url.pathname.startsWith('/console/account')}
<Button secondary on:click={() => wizard.start(ChangeOrganizationTierCloud)}>
Upgrade
</Button>
+16 -1
View File
@@ -277,6 +277,22 @@ export class Billing {
);
}
async deleteOrganization(organizationId: string): Promise<Organization> {
const path = `/organizations/${organizationId}`;
const params = {
organizationId
};
const uri = new URL(this.client.config.endpoint + path);
return await this.client.call(
'DELETE',
uri,
{
'content-type': 'application/json'
},
params
);
}
async getPlan(organizationId: string): Promise<Plan> {
const path = `/organizations/${organizationId}/plan`;
const params = {
@@ -482,7 +498,6 @@ export class Billing {
);
}
// TODO: add date range
async listUsage(
organizationId: string,
startDate: string = null,
-5
View File
@@ -87,25 +87,20 @@ export const failedInvoice = cachedStore<
});
export type TierData = {
price: number;
name: string;
description: string;
collaboratorPrice?: number;
};
export const tierFree: TierData = {
price: 0,
name: 'Starter',
description: 'For personal, passion projects.'
};
export const tierPro: TierData = {
price: 15,
name: 'Pro',
description: 'For pro developers and production projects that need the ability to scale.'
};
export const tierScale: TierData = {
price: 685,
name: 'Scale',
description: 'For scaling teams that need dedicated support.'
};
+1
View File
@@ -9,6 +9,7 @@ export type Organization = Models.Team<Record<string, unknown>> & {
budgetAlerts: number[];
paymentMethodId: string;
backupPaymentMethodId: string;
markedForDeletion: boolean;
billingLimits: BillingLimits;
billingCurrentInvoiceDate: string;
billingNextInvoiceDate: string;
+1 -2
View File
@@ -416,8 +416,7 @@
</svelte:fragment>
</HeaderAlert>
{/if}
<!-- TODO: add variable from backend that indicates org is due to be deleted -->
{#if false}
{#if $organization?.markedForDeletion && !$page.url.pathname.includes('/console/account')}
<HeaderAlert title="Organization flagged for deletion">
<svelte:fragment>
All existing projects in the {$organization.name} organization have been paused.
@@ -11,6 +11,7 @@
import Delete from './deleteOrganization.svelte';
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
export let data;
let name: string;
let showDelete = false;
@@ -89,4 +90,4 @@
{/if}
</Container>
<Delete bind:showDelete />
<Delete bind:showDelete invoices={data.invoices} />
@@ -2,9 +2,11 @@ import type { PageLoad } from './$types';
import { Dependencies } from '$lib/constants';
import { sdk } from '$lib/stores/sdk';
export const load: PageLoad = async ({ depends }) => {
export const load: PageLoad = async ({ depends, parent }) => {
const { organization } = await parent();
depends(Dependencies.ORGANIZATION);
return {
projects: await sdk.forConsole.projects.list()
projects: await sdk.forConsole.projects.list(),
invoices: await sdk.forConsole.billing.listInvoices(organization.$id)
};
};
@@ -10,21 +10,26 @@
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
import { projects } from '../store';
import { toLocaleDate } from '$lib/helpers/date';
import { isCloud } from '$lib/system';
import type { InvoiceList } from '$lib/sdk/billing';
export let showDelete = false;
export let invoices: InvoiceList;
let error: string = null;
//TODO: replace variable with value from method
const TEMPORARY_SET_FOR_DELETION = true;
async function deleteOrg() {
try {
await sdk.forConsole.teams.delete($organization.$id);
await invalidate(Dependencies.ACCOUNT);
if (isCloud) {
await sdk.forConsole.billing.deleteOrganization($organization.$id);
} else {
await sdk.forConsole.teams.delete($organization.$id);
}
addNotification({
type: 'success',
message: `${$organization.name} has been deleted`
});
await invalidate(Dependencies.ACCOUNT);
await invalidate(Dependencies.ORGANIZATION);
trackEvent(Submit.OrganizationDelete);
if ($organizationList?.total > 1) {
goto(`${base}/console/`);
@@ -37,6 +42,8 @@
trackError(e, Submit.OrganizationDelete);
}
}
$: upcomingInvoice = invoices.invoices.find((i) => i.status === 'upcoming' && i.amount > 0);
</script>
<Modal
@@ -47,7 +54,7 @@
icon="exclamation"
state="warning"
headerDivider={false}>
{#if TEMPORARY_SET_FOR_DELETION}
{#if upcomingInvoice}
<p data-private>
The organization <b>{$organization.name}</b> will be flagged for deletion.
</p>
+8 -1
View File
@@ -9,6 +9,7 @@
import { addNotification } from '$lib/stores/notifications';
import { wizard } from '$lib/stores/wizard';
import { VARS } from '$lib/system';
import { organization } from '$lib/stores/organization';
onDestroy(() => {
$supportData = {
@@ -37,7 +38,13 @@
firstName: $user?.name ?? '',
message: $supportData.message,
tags: ['cloud'],
customFields: [{ id: '41612', value: $supportData.category }]
customFields: [
{ id: '41612', value: $supportData.category },
{ id: '48493', value: $user?.name ?? '' },
{ id: '48492', value: $organization.$id ?? '' },
// { id: '48491', value: $user?.projectId ?? '' },
{ id: '48490', value: $user?.$id ?? '' }
]
})
});
trackEvent(Submit.SupportTicket);
@@ -3,7 +3,7 @@
import { Pill } from '$lib/elements';
import { InputText, FormList } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
import { tierFree, tierPro, tierScale } from '$lib/stores/billing';
import { plansInfo, tierFree, tierPro, tierScale } from '$lib/stores/billing';
import { organizationList, type Organization } from '$lib/stores/organization';
import { updateStepStatus } from '$lib/stores/wizard';
import { createOrganization, createOrgSteps } from './store';
@@ -28,6 +28,10 @@
$createOrgSteps = updateStepStatus($createOrgSteps, 3, false);
$createOrgSteps = updateStepStatus($createOrgSteps, 4, false);
}
$: freePlan = $plansInfo.plans.find((p) => p.$id === 'tier-0');
$: proPlan = $plansInfo.plans.find((p) => p.$id === 'tier-1');
$: scalePlan = $plansInfo.plans.find((p) => p.$id === 'tier-2');
</script>
<WizardStep>
@@ -81,7 +85,7 @@
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
class:u-opacity-50={disabled}>
<h4 class="body-text-2 u-bold">
{tierFree.name} - ${tierFree.price}/month
{tierFree.name} - ${freePlan?.price}/month
</h4>
<p class="u-color-text-gray u-small">{tierFree.description}</p>
</div>
@@ -94,7 +98,7 @@
<svelte:fragment slot="custom">
<div class="u-flex u-flex-vertical u-gap-4 u-width-full-line">
<h4 class="body-text-2 u-bold">
{tierPro.name} - ${tierPro.price}/month per organization member + exta
{tierPro.name} - ${proPlan.price}/month per organization member + exta
usage
</h4>
<p class="u-color-text-gray u-small">
@@ -116,7 +120,7 @@
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
class:u-opacity-50={disabled}>
<h4 class="body-text-2 u-bold">
{tierScale.name} - ${tierScale.price}/month + extra usage
{tierScale.name} - ${scalePlan.price}/month + extra usage
</h4>
<p class="u-color-text-gray u-small">
{tierScale.description}
@@ -86,6 +86,10 @@
$changeOrganizationTier.billingPlan = 'tier-1';
}
});
$: freePlan = $plansInfo.plans.find((p) => p.$id === 'tier-0');
$: proPlan = $plansInfo.plans.find((p) => p.$id === 'tier-1');
$: scalePlan = $plansInfo.plans.find((p) => p.$id === 'tier-2');
</script>
<WizardStep>
@@ -114,7 +118,7 @@
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
class:u-opacity-50={disabled}>
<h4 class="body-text-2 u-bold">
{tierFree.name} - ${tierFree.price}/month
{tierFree.name} - ${freePlan.price}/month
</h4>
<p class="u-color-text-gray u-small">{tierFree.description}</p>
</div>
@@ -139,7 +143,7 @@
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
class:u-opacity-50={disabled}>
<h4 class="body-text-2 u-bold">
{tierPro.name} - ${tierPro.price}/month per organization member + extra
{tierPro.name} - ${proPlan.price}/month per organization member + extra
usage
</h4>
<p class="u-color-text-gray u-small">
@@ -167,7 +171,7 @@
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
class:u-opacity-50={disabled}>
<h4 class="body-text-2 u-bold">
{tierScale.name} - ${tierScale.price}/month + extra usage
{tierScale.name} - ${scalePlan.price}/month + extra usage
</h4>
<p class="u-color-text-gray u-small">
{tierScale.description}
@@ -167,11 +167,21 @@
<p class="text">Additional members ({collaboratorsNumber})</p>
<p class="text">${collaboratorPrice * collaboratorsNumber}</p>
</span>
{#if showCoupon && couponData?.status !== 'error'}
<span class="u-flex u-main-space-between">
<p class="text">Credits applied ({couponData.credits})</p>
<p class="text">-${couponData.credits}</p>
</span>
{/if}
{/if}
<div class="u-sep-block-start" />
<span class="u-flex u-main-space-between">
<p class="text">Estimated total</p>
<p class="text">${totalExpences}</p>
<p class="text">Estimated total (in USD)</p>
<p class="text">
${showCoupon && couponData?.status !== 'error'
? totalExpences - couponData.credits || 0
: totalExpences}
</p>
</span>
<p class="text u-margin-block-start-16">