Merge pull request #1048 from appwrite/feat-add-members-usage-page

Feat: add members count to usage page
This commit is contained in:
Arman
2024-05-17 16:12:23 +02:00
committed by GitHub
6 changed files with 140 additions and 8 deletions
@@ -0,0 +1,37 @@
<script lang="ts">
import { trackEvent } from '$lib/actions/analytics';
import { BillingPlan } from '$lib/constants';
import { Button } from '$lib/elements/forms';
import { tierToPlan } from '$lib/stores/billing';
import { wizard } from '$lib/stores/wizard';
import ChangeOrganizationTierCloud from '$routes/console/changeOrganizationTierCloud.svelte';
import { Card } from '..';
export let service: string;
export let eventSource: string;
</script>
<Card>
<slot>
<div class="u-flex u-flex-vertical u-main-center u-cross-center u-gap-8">
<h6 class="body-text-1 u-bold u-trim-1">Upgrade to add {service}</h6>
<p class="text u-text-center">
Upgrade to a {tierToPlan(BillingPlan.PRO).name} plan to add {service} to your organization
</p>
<Button
class="u-margin-block-start-16"
secondary
fullWidthMobile
on:click={() => {
trackEvent('click_organization_upgrade', {
from: 'button',
source: eventSource
});
wizard.start(ChangeOrganizationTierCloud);
}}>
Upgrade
</Button>
</div>
</slot>
</Card>
+1
View File
@@ -1,2 +1,3 @@
export { default as PaymentBoxes } from './paymentBoxes.svelte';
export { default as CouponInput } from './couponInput.svelte';
export { default as EmptyCardCloud } from './emptyCardCloud.svelte';
+8 -5
View File
@@ -3,6 +3,7 @@
export let items = [];
export let limit = 5;
export let hideFooter = false;
let offset = 0;
@@ -10,9 +11,11 @@
$: paginatedItems = items.slice(offset, offset + limit);
</script>
<slot {paginatedItems} />
<slot {paginatedItems} {limit} />
<div class="u-flex u-margin-block-start-32 u-main-space-between">
<p class="text">Total results: {total}</p>
<PaginationInline {limit} bind:offset sum={total} hidePages />
</div>
{#if !hideFooter}
<div class="u-flex u-margin-block-start-32 u-main-space-between">
<p class="text">Total results: {total}</p>
<PaginationInline {limit} bind:offset sum={total} hidePages />
</div>
{/if}
@@ -14,6 +14,7 @@
import type { OrganizationUsage } from '$lib/sdk/billing';
import { BillingPlan } from '$lib/constants';
import { trackEvent } from '$lib/actions/analytics';
import TotalMembers from './totalMembers.svelte';
export let data;
@@ -298,6 +299,7 @@
{/if}
</svelte:fragment>
</CardGrid>
<TotalMembers members={data?.organizationMembers} />
<p class="text common-section u-color-text-gray">
Metrics are estimates updated every 24 hours and may not accurately reflect your invoice.
@@ -36,9 +36,10 @@ export const load: PageLoad = async ({ params, parent }) => {
endDate = currentInvoice.to;
}
const [invoices, usage] = await Promise.all([
const [invoices, usage, organizationMembers] = await Promise.all([
sdk.forConsole.billing.listInvoices(org.$id, [Query.orderDesc('from')]),
sdk.forConsole.billing.listUsage(params.organization, startDate, endDate)
sdk.forConsole.billing.listUsage(params.organization, startDate, endDate),
sdk.forConsole.teams.listMemberships(params.organization)
]);
const queries: string[] = [];
@@ -58,6 +59,7 @@ export const load: PageLoad = async ({ params, parent }) => {
organizationUsage: usage,
projectNames: projectNames.projects,
invoices,
currentInvoice
currentInvoice,
organizationMembers
};
};
@@ -0,0 +1,87 @@
<script lang="ts">
import { tooltip } from '$lib/actions/tooltip';
import { AvatarInitials, CardGrid, Heading, Paginator } from '$lib/components';
import { EmptyCardCloud } from '$lib/components/billing';
import { BillingPlan } from '$lib/constants';
import { Button } from '$lib/elements/forms';
import {
TableBody,
TableCell,
TableCellHead,
TableCellText,
TableHeader,
TableRow,
TableScroll
} from '$lib/elements/table';
import { toLocaleDate } from '$lib/helpers/date';
import { formatCurrency } from '$lib/helpers/numbers';
import { plansInfo, tierToPlan } from '$lib/stores/billing';
import { newMemberModal, organization } from '$lib/stores/organization';
import type { Models } from '@appwrite.io/console';
export let members: Models.MembershipList;
$: total = members?.total ?? 0;
$: plan = $plansInfo?.get($organization?.billingPlan);
</script>
<CardGrid>
<Heading tag="h6" size="7">Members</Heading>
<p class="text">The number of members in your organization.</p>
<svelte:fragment slot="aside">
{#if $organization.billingPlan !== BillingPlan.STARTER}
<div class="u-flex u-flex-vertical">
<div class="u-flex u-main-space-between">
<p>
<span class="heading-level-4">{total}</span>
<span class="body-text-1 u-bold">Members</span>
</p>
<Button secondary on:click={() => newMemberModal.set(true)}>
<span class="icon-plus"></span> <span class="text">Invite</span>
</Button>
</div>
<p class="body-text-2">
Unlimited
<span
class="icon-info"
use:tooltip={{
content: `You can add unlimited organization members on the ${tierToPlan($organization.billingPlan).name} plan for ${formatCurrency(plan.addons.member.price)} each per billing period.`
}}></span>
</p>
</div>
<Paginator
items={members.memberships}
let:paginatedItems
hideFooter={members?.total <= 5}>
<TableScroll noMargin noStyles>
<TableHeader>
<TableCellHead>Members</TableCellHead>
<TableCellHead>Joined</TableCellHead>
</TableHeader>
<TableBody>
{#each paginatedItems as member}
<TableRow>
<TableCell title="name">
<div class="u-flex u-gap-12 u-cross-center">
<AvatarInitials size={32} name={member.userName} />
<span class="text u-trim">
{member.userName ? member.userName : member.userEmail}
</span>
</div>
</TableCell>
<TableCellText title="joined">
{member.joined
? toLocaleDate(member.joined)
: toLocaleDate(member.$createdAt)}
</TableCellText>
</TableRow>
{/each}
</TableBody>
</TableScroll>
</Paginator>
{:else}
<EmptyCardCloud service="members" eventSource="organization_usage" />
{/if}
</svelte:fragment>
</CardGrid>