Merge branch 'feat-profiles' of https://github.com/appwrite/console into feat-profiles

This commit is contained in:
Torsten Dittmann
2025-12-16 16:58:48 +04:00
5 changed files with 815 additions and 46 deletions
+756 -7
View File
File diff suppressed because it is too large Load Diff
+33 -29
View File
@@ -68,9 +68,12 @@
organizations: Array<{
name: string;
$id: string;
name: string;
isSelected: boolean;
showUpgrade: boolean;
tierName: string;
billingCurrentInvoiceDate?: string;
billingNextInvoiceDate?: string;
}>;
showAccountMenu: boolean;
currentProject?: Models.Project;
@@ -80,12 +83,19 @@
logo,
organizations,
avatar,
currentProject = undefined,
sideBarIsOpen = $bindable(false),
showAccountMenu = $bindable(false),
currentProject = undefined
showAccountMenu = $bindable(false)
}: Props = $props();
let credits = $state(0);
let creditsUsed = $state(0);
let showSupport = $state(false);
let activeTheme = $state($app.theme);
let shouldAnimateThemeToggle = $state(false);
const plan = $derived(page.data.currentPlan as Models.BillingPlan);
const currentOrg = $derived(organizations.find((org) => org.isSelected));
function updateTheme(theme: 'light' | 'dark' | 'auto') {
const themeInUse =
@@ -114,36 +124,30 @@
}
}
let activeTheme = $state($app.theme);
let shouldAnimateThemeToggle = $state(false);
async function fetchImagineCredits(org: (typeof organizations)[number]) {
const startDate = org.billingCurrentInvoiceDate;
const endDate = org.billingNextInvoiceDate;
const usage = await sdk.forConsole.billing.listUsage(org.$id, startDate, endDate);
creditsUsed = usage.imagineCreditsTotal;
const creditsLimit = plan?.limits?.credits ?? 0;
credits = Math.max(0, creditsLimit - creditsUsed);
}
beforeNavigate(() => (showAccountMenu = false));
onMount(() => {
if (resolvedProfile.showExtendedAccountsMenu) {
fetchImagineCredits(currentOrg);
}
});
$effect(() => {
if (activeTheme) {
updateTheme(activeTheme);
}
});
const currentOrg = $derived(
organizations.find((org) => org.isSelected) as unknown as Models.Organization
);
const plan = page.data.currentPlan as Models.BillingPlan;
let credits = $state(0);
async function fetchImagineCredits(org: Models.Organization) {
const startDate: string = currentOrg.billingCurrentInvoiceDate;
const endDate: string = currentOrg.billingNextInvoiceDate;
const usage = await sdk.forConsole.billing.listUsage(org.$id, startDate, endDate);
credits = usage.imagineCreditsTotal;
}
beforeNavigate(() => (showAccountMenu = false));
onMount(() => {
if (resolvedProfile.showExtendedAccountsMenu) {
fetchImagineCredits(currentOrg);
}
});
</script>
<Navbar.Base --border-width-s="none" style="top: {$headerAlert.top}px; z-index: 100;">
@@ -300,15 +304,15 @@
direction="row"
justifyContent="space-between"
alignItems="center"
>{credits} Credits left
>{credits} Credit(s) left
</Layout.Stack>
<svelte:fragment slot="more">
<ProgressBar
maxSize={plan.limits.credits ?? 0}
data={[
{
size: credits,
color: 'hsl(var(--color-information-100))'
size: creditsUsed,
color: 'var(--bgcolor-neutral-invert)'
}
]} />
</svelte:fragment>
+5 -3
View File
@@ -163,11 +163,13 @@
organizations: $organizationList.teams.map((org) => {
const billingPlan = org['billingPlan'];
return {
name: org.name,
$id: org.$id,
showUpgrade: isFreePlan(billingPlan),
name: org.name,
isSelected: $organization?.$id === org.$id,
showUpgrade: isCloud ? isFreePlan(billingPlan) : false,
tierName: isCloud ? tierToPlan(billingPlan).name : null,
isSelected: $organization?.$id === org.$id
billingNextInvoiceDate: isCloud ? org['billingNextInvoiceDate'] : undefined,
billingCurrentInvoiceDate: isCloud ? org['billingCurrentInvoiceDate'] : undefined
};
}),
+1 -1
View File
@@ -57,7 +57,7 @@
},
onUpgrade: async () => {
const organization = get(organizationStore).$id;
goto(
await goto(
resolve('/(console)/organization-[organization]/change-plan', {
organization: organization
})
@@ -1,6 +1,6 @@
<script lang="ts">
import { afterNavigate, goto, invalidate } from '$app/navigation';
import { base } from '$app/paths';
import { base, resolve } from '$app/paths';
import { page } from '$app/state';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { PlanComparisonBox, PlanSelection, SelectPaymentMethod } from '$lib/components/billing';
@@ -36,7 +36,7 @@
import type { OrganizationUsage } from '$lib/sdk/billing';
import type { Models } from '@appwrite.io/console';
import { toLocaleDate } from '$lib/helpers/date';
import { resolvedProfile } from '$lib/profiles/index.svelte';
import { ProfileMode, resolvedProfile } from '$lib/profiles/index.svelte';
import { isFreePlan, isPaidPlan } from '$lib/helpers/billing.js';
export let data;
@@ -45,7 +45,7 @@
let selectedPlan: BillingPlan = data.plan as BillingPlan;
let previousPage: string = base;
let previousPage: string = resolve('/');
let showExitModal = false;
let formComponent: Form;
let usageLimitsComponent:
@@ -116,6 +116,18 @@
}
});
async function compatNavigation(url: string) {
if (resolvedProfile.id === ProfileMode.STUDIO) {
if (window) {
window.location.href = url;
} else {
await goto(url);
}
} else {
await goto(url);
}
}
async function loadPaymentMethods() {
paymentMethods = await sdk.forConsole.billing.listPaymentMethods();
return paymentMethods;
@@ -178,7 +190,7 @@
await Promise.all([trackDowngradeFeedback(), invalidate(Dependencies.ORGANIZATION)]);
await goto(previousPage);
await compatNavigation(previousPage);
addNotification({
type: 'success',
@@ -204,7 +216,8 @@
await invalidate(Dependencies.ACCOUNT);
await invalidate(Dependencies.ORGANIZATION);
await goto(previousPage);
await compatNavigation(previousPage);
addNotification({
type: 'success',
message: 'Your organization has been upgraded'
@@ -275,7 +288,8 @@
await invalidate(Dependencies.ACCOUNT);
await invalidate(Dependencies.ORGANIZATION);
await goto(previousPage);
await compatNavigation(previousPage);
addNotification({
type: 'success',
message: 'Your organization has been upgraded'