Merge pull request #727 from appwrite/fix-missing-events-and-credits

chore: add missing event
This commit is contained in:
Torsten Dittmann
2024-01-26 13:13:55 +01:00
committed by GitHub
21 changed files with 161 additions and 30 deletions
@@ -55,7 +55,7 @@
<div>
<span class="icon-exclamation-circle u-color-text-danger" />
<span>
{couponData.code} is not a valid promo code
{couponData.code.toUpperCase()} is not a valid promo code
</span>
</div>
{:else if couponData?.status === 'active'}
@@ -64,11 +64,11 @@
<span class="icon-tag u-color-text-success" />
<slot data={couponData}>
<span>
{couponData.code} applied (-${couponData.credits})
{couponData.code.toUpperCase()} applied (-${couponData.credits})
</span>
</slot>
</div>
<Button text on:click={removeCoupon}>Remove</Button>
<Button round text on:click={removeCoupon}><span class="icon-x"></span></Button>
</div>
{/if}
</FormList>
+1 -1
View File
@@ -13,7 +13,7 @@
{#if total}
{#each elements as element}
{@const value = element[variableName]?.toString()}
<div class="box">
<div class="box" data-private>
<InputRadio
id={`${name}-${value}`}
{value}
+12 -1
View File
@@ -11,6 +11,8 @@
import { isCloud } from '$lib/system';
import { organization } from '$lib/stores/organization';
import { BillingPlan } from '$lib/constants';
import ChangeOrganizationTierCloud from '$routes/console/changeOrganizationTierCloud.svelte';
import { trackEvent } from '$lib/actions/analytics';
export let show = false;
@@ -43,7 +45,16 @@
{/if}
</div>
{#if $organization?.billingPlan === BillingPlan.STARTER}
<Button fullWidth href="https://appwrite.io/pricing" external>
<Button
fullWidth
external
on:click={() => {
wizard.start(ChangeOrganizationTierCloud);
trackEvent('click_organization_upgrade', {
from: 'button',
source: 'support_menu'
});
}}>
<span class="text">Get Premium support</span>
</Button>
{:else}
+10 -1
View File
@@ -1,4 +1,5 @@
<script lang="ts">
import { trackEvent } from '$lib/actions/analytics';
import { getServiceLimit, type PlanServices } from '$lib/stores/billing';
import { wizard } from '$lib/stores/wizard';
import { isCloud } from '$lib/system';
@@ -10,6 +11,7 @@
export let service: PlanServices = null;
export let name = service;
export let total: number = null;
export let event: string = null;
let columns = 0;
@@ -34,7 +36,14 @@
<span class="u-flex u-gap-24 u-main-center u-cross-center">
<slot name="limit" {upgradeMethod} {limit}>
<span class="text">Upgrade your plan to add {name} to your organization</span>
<Button secondary on:click={upgradeMethod}>Upgrade plan</Button>
<Button
secondary
on:click={upgradeMethod}
on:click={() =>
trackEvent('click_organization_upgrade', {
from: 'button',
source: event ?? 'table_row_limit_reached'
})}>Upgrade plan</Button>
</slot>
</span>
</td>
+13 -3
View File
@@ -18,6 +18,7 @@
import { ContainerButton } from '.';
import { Button } from '$lib/elements/forms';
import { BillingPlan } from '$lib/constants';
import { trackEvent } from '$lib/actions/analytics';
export let isFlex = true;
export let title: string;
@@ -92,8 +93,12 @@
<span class="text">
You've reached the {services} limit for the {tier} plan. <Button
link
on:click={upgradeMethod}>Upgrade</Button> your organization for additional
resources.
on:click={upgradeMethod}
on:click={() =>
trackEvent('click_organization_upgrade', {
from: 'button',
source: 'inline_alert'
})}>Upgrade</Button> your organization for additional resources.
</span>
</Alert>
{/if}
@@ -124,7 +129,12 @@
{title.toLocaleLowerCase()} per project on the {tier} plan.
{#if $organization?.billingPlan === BillingPlan.STARTER}<Button
link
on:click={upgradeMethod}>Upgrade</Button>
on:click={upgradeMethod}
on:click={() =>
trackEvent('click_organization_upgrade', {
from: 'button',
source: 'resource_limit_tag'
})}>Upgrade</Button>
for addtional {title.toLocaleLowerCase()}.
{/if}
</p>
+7 -1
View File
@@ -121,7 +121,13 @@
{#if isCloud && $organization?.billingPlan === BillingPlan.STARTER && !$page.url.pathname.startsWith('/console/account')}
<Button
disabled={$organization?.markedForDeletion}
on:click={() => wizard.start(ChangeOrganizationTierCloud)}>
on:click={() => {
wizard.start(ChangeOrganizationTierCloud);
trackEvent('click_organization_upgrade', {
from: 'button',
source: 'top_nav'
});
}}>
Upgrade
</Button>
{/if}
+1 -1
View File
@@ -36,7 +36,7 @@
class={icon ? `icon-${icon}` : ''}
aria-hidden="true" />
</div>
<div class="alert-sticky-content">
<div class="alert-sticky-content" data-private>
{#if title}
<h4 class="alert-sticky-title">{title}</h4>
{/if}
@@ -88,6 +88,7 @@
org.$id,
$changeOrganizationTier.couponCode
);
trackEvent(Submit.CreditRedeem);
}
//Add budget
@@ -56,6 +56,12 @@
);
}
//Add coupon
if ($createOrganization?.couponCode) {
await sdk.forConsole.billing.addCredit(org.$id, $createOrganization.couponCode);
trackEvent(Submit.CreditRedeem);
}
//Add collaborators
if ($createOrganization?.collaborators?.length) {
$createOrganization.collaborators.forEach(async (collaborator) => {
@@ -110,7 +116,8 @@
paymentMethodId: null,
collaborators: [],
billingAddressId: null,
taxId: null
taxId: null,
couponCode: null
};
});
@@ -71,9 +71,10 @@
<p class="text">Appwrite credit will automatically be applied to your next invoice.</p>
<svelte:fragment slot="aside">
<div class="u-flex u-cross-center u-main-space-between">
<h4 class="body-text-1 u-bold">
Credit balance <span class="inline-tag">${balance}</span>
</h4>
<div class="u-flex u-gap-8 u-cross-center">
<h4 class="body-text-1 u-bold">Credit balance</h4>
<span class="inline-tag">${balance}</span>
</div>
{#if creditList?.total}
<Button secondary on:click={handleCredits}>
<span class="icon-plus" aria-hidden="true"></span>
@@ -8,6 +8,8 @@
import { addNotification } from '$lib/stores/notifications';
import { organization } from '$lib/stores/organization';
import { sdk } from '$lib/stores/sdk';
import { wizard } from '$lib/stores/wizard';
import ChangeOrganizationTierCloud from '$routes/console/changeOrganizationTierCloud.svelte';
import { onMount } from 'svelte';
let capActive = false;
@@ -92,7 +94,19 @@
</svelte:fragment>
<svelte:fragment slot="actions">
<Button disabled={$organization?.billingBudget === budget} submit>Update</Button>
{#if $organization?.billingPlan === BillingPlan.STARTER}
<Button
secondary
on:click={() => {
wizard.start(ChangeOrganizationTierCloud);
trackEvent('click_organization_upgrade', {
from: 'button',
source: 'billing_budget_cap'
});
}}>Upgrade to Pro</Button>
{:else}
<Button disabled={$organization?.billingBudget === budget} submit>Update</Button>
{/if}
</svelte:fragment>
</CardGrid>
</Form>
@@ -15,6 +15,7 @@
import { abbreviateNumber, formatNumberWithCommas } from '$lib/helpers/numbers';
import { humanFileSize } from '$lib/helpers/sizeConvertion';
import { BillingPlan } from '$lib/constants';
import { trackEvent } from '$lib/actions/analytics';
let currentInvoice: Invoice;
const today = new Date();
@@ -136,7 +137,12 @@
</Button>
<Button
disabled={$organization?.markedForDeletion}
on:click={() => wizard.start(ChangeOrganizationTierCloud)}>
on:click={() => wizard.start(ChangeOrganizationTierCloud)}
on:click={() =>
trackEvent('click_organization_upgrade', {
from: 'button',
source: 'billing_tab'
})}>
Upgrade
</Button>
</div>
@@ -145,7 +151,12 @@
<Button
text
disabled={$organization?.markedForDeletion}
on:click={() => wizard.start(ChangeOrganizationTierCloud)}>
on:click={() => wizard.start(ChangeOrganizationTierCloud)}
on:click={() =>
trackEvent('click_organization_plan_update', {
from: 'button',
source: 'billing_tab'
})}>
Change plan
</Button>
<Button
@@ -4,6 +4,7 @@
import type { Coupon } from '$lib/sdk/billing';
import { sdk } from '$lib/stores/sdk';
import { wizard } from '$lib/stores/wizard';
import { onMount } from 'svelte';
import { addCreditWizardStore } from '../store';
let coupon: string;
@@ -18,6 +19,7 @@
try {
const response = await sdk.forConsole.billing.getCoupon(coupon);
couponData = response;
$addCreditWizardStore.coupon = coupon;
coupon = null;
} catch (error) {
couponData.code = coupon;
@@ -26,6 +28,13 @@
throw new Error(error);
}
}
onMount(() => {
if ($addCreditWizardStore.coupon) {
coupon = $addCreditWizardStore.coupon;
validateCoupon();
}
});
</script>
<WizardStep beforeSubmit={validateCoupon}>
@@ -41,6 +50,6 @@
$addCreditWizardStore.coupon = e.detail.code;
}}
let:data>
<span>{data.code} has been successfully added</span>
<span>{data.code.toUpperCase()} has been successfully added</span>
</CouponInput>
</WizardStep>
@@ -14,6 +14,7 @@
import { goto } from '$app/navigation';
import { last } from '$lib/helpers/array';
import { BillingPlan } from '$lib/constants';
import { trackEvent } from '$lib/actions/analytics';
export let show = false;
const plan = $plansInfo?.get($organization.billingPlan);
@@ -89,13 +90,20 @@
on:click={() => {
show = false;
goto(`/console/organization-${$organization.$id}/usage`);
}}>View usage</Button>
}}>
View usage
</Button>
<Button
on:click={() => {
show = false;
wizard.start(ChangeOrganizationTierCloud);
}}>Upgrade plan</Button>
trackEvent('click_organization_upgrade', {
from: 'button',
source: 'limit_reached_modal'
});
}}>
Upgrade plan
</Button>
</div>
</div>
</svelte:fragment>
@@ -70,7 +70,10 @@
<TableCellHead width={90} />
<TableCellHead width={30} />
</TableHeader>
<TableBody service="members" total={data.organizationMembers.total}>
<TableBody
service="members"
total={data.organizationMembers.total}
event="members_list">
{#each data.organizationMembers.memberships as member}
<TableRow>
<TableCell title="Name">
@@ -13,6 +13,7 @@
import { accumulateFromEndingTotal, total } from '$lib/layout/usage.svelte';
import type { OrganizationUsage } from '$lib/sdk/billing';
import { BillingPlan } from '$lib/constants';
import { trackEvent } from '$lib/actions/analytics';
export let data;
@@ -42,7 +43,14 @@
<Heading tag="h2" size="5">Usage</Heading>
{#if $organization?.billingPlan === BillingPlan.STARTER}
<Button on:click={() => wizard.start(ChangeOrganizationTierCloud)}>
<Button
on:click={() => {
wizard.start(ChangeOrganizationTierCloud);
trackEvent('click_organization_upgrade', {
from: 'button',
source: 'organization_usage'
});
}}>
<span class="text">Upgrade</span>
</Button>
{/if}
@@ -6,6 +6,7 @@
import { createOrganization } from './store';
import type { AddressesList } from '$lib/sdk/billing';
import { RadioBoxes } from '$lib/components';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
let options = [
{
@@ -33,7 +34,9 @@
addressLine2 ? addressLine2 : undefined
);
$createOrganization.billingAddressId = response.$id;
trackEvent(Submit.BillingAddressCreate);
} catch (error) {
trackError(error, Submit.BillingAddressCreate);
throw new Error(error.message);
}
}
@@ -1,9 +1,11 @@
<script lang="ts">
import { Box, CreditCardBrandImage } from '$lib/components';
import { CouponInput } from '$lib/components/billing';
import { BillingPlan } from '$lib/constants';
import { Pill } from '$lib/elements';
import { toLocaleDate } from '$lib/helpers/date';
import { WizardStep } from '$lib/layout';
import type { Coupon } from '$lib/sdk/billing';
import { plansInfo } from '$lib/stores/billing';
import { sdk } from '$lib/stores/sdk';
import { createOrganization, createOrganizationFinalAction } from './store';
@@ -15,6 +17,13 @@
const today = new Date();
const billingPayDate = new Date(today.getTime() + 44 * 24 * 60 * 60 * 1000);
let coupon: string = null;
let couponData: Partial<Coupon> = {
code: null,
status: null,
credits: null
};
async function fetchCard() {
try {
const card = await sdk.forConsole.billing.getPaymentMethod(
@@ -77,6 +86,10 @@
{/if}
<Box class="u-margin-block-start-32 u-flex u-flex-vertical u-gap-16" radius="small">
{#if $createOrganization.billingPlan !== BillingPlan.STARTER}
<CouponInput
bind:coupon
bind:couponData
on:validation={(e) => ($createOrganization.couponCode = e.detail.code)} />
<span class="u-flex u-main-space-between">
<p class="text">{plan.name} plan</p>
<p class="text">${plan.price}</p>
@@ -85,11 +98,23 @@
<p class="text">Additional members ({collaboratorsNumber})</p>
<p class="text">${collaboratorPrice * collaboratorsNumber}</p>
</span>
{#if couponData?.status === 'active'}
<span class="u-flex u-main-space-between">
<p class="text">Credits applied ({couponData.credits})</p>
<p class="text">-${couponData.credits}</p>
</span>
{/if}
<div class="u-sep-block-start" />
{/if}
<span class="u-flex u-main-space-between">
<p class="text">Estimated total</p>
<p class="text">${totalExpences}</p>
<p class="text">
${couponData?.status === 'active'
? totalExpences - couponData.credits >= 0
? totalExpences - couponData.credits
: 0
: totalExpences}
</p>
</span>
{#if $createOrganization.billingPlan !== BillingPlan.STARTER}
@@ -15,6 +15,7 @@ export const createOrganization = writable<{
collaborators?: string[];
billingBudget?: number;
taxId?: string;
couponCode?: string;
}>({
id: null,
name: null,
@@ -22,5 +23,6 @@ export const createOrganization = writable<{
paymentMethodId: null,
collaborators: [],
billingAddressId: null,
taxId: null
taxId: null,
couponCode: null
});
@@ -7,6 +7,7 @@
import { organization } from '$lib/stores/organization';
import type { AddressesList } from '$lib/sdk/billing';
import { RadioBoxes } from '$lib/components';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
let options = [
{
@@ -34,7 +35,9 @@
addressLine2 ? addressLine2 : undefined
);
$changeOrganizationTier.billingAddressId = response.$id;
trackEvent(Submit.BillingAddressCreate);
} catch (error) {
trackError(error, Submit.BillingAddressCreate);
throw new Error(error.message);
}
}
@@ -97,11 +97,11 @@
{/if}
<Box class="u-margin-block-start-32 u-flex u-flex-vertical u-gap-16" radius="small">
<CouponInput
bind:coupon
bind:couponData
on:validation={(e) => ($changeOrganizationTier.couponCode = e.detail.code)} />
{#if $changeOrganizationTier.billingPlan !== BillingPlan.STARTER}
<CouponInput
bind:coupon
bind:couponData
on:validation={(e) => ($changeOrganizationTier.couponCode = e.detail.code)} />
<span class="u-flex u-main-space-between">
<p class="text">{plan.name} plan</p>
<p class="text">${plan.price}</p>