diff --git a/package.json b/package.json
index f12341aefc..bb0bc7f835 100644
--- a/package.json
+++ b/package.json
@@ -22,7 +22,7 @@
},
"dependencies": {
"@ai-sdk/svelte": "^1.1.24",
- "@appwrite.io/console": "^1.9.0",
+ "@appwrite.io/console": "https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@56743f5",
"@appwrite.io/pink-icons": "0.25.0",
"@appwrite.io/pink-icons-svelte": "^2.0.0-RC.1",
"@appwrite.io/pink-legacy": "^1.0.3",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a3664a807f..598822dd34 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -12,8 +12,8 @@ importers:
specifier: ^1.1.24
version: 1.1.24(svelte@5.25.3)(zod@3.24.3)
'@appwrite.io/console':
- specifier: ^1.9.0
- version: 1.9.0
+ specifier: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@56743f5
+ version: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@56743f5
'@appwrite.io/pink-icons':
specifier: 0.25.0
version: 0.25.0
@@ -257,8 +257,9 @@ packages:
'@analytics/type-utils@0.6.2':
resolution: {integrity: sha512-TD+xbmsBLyYy/IxFimW/YL/9L2IEnM7/EoV9Aeh56U64Ify8o27HJcKjo38XY9Tcn0uOq1AX3thkKgvtWvwFQg==}
- '@appwrite.io/console@1.9.0':
- resolution: {integrity: sha512-g8+zfdBF8mz7tRUER4CGVe5FHWQVLp8TlY/UOGCZ2TgUF1qnpNu/DhiQgph8uF+QZ9jDKCLAAZlP5//9t7ckWA==}
+ '@appwrite.io/console@https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@56743f5':
+ resolution: {tarball: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@56743f5}
+ version: 1.9.0
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@ee1b7788cd3f877c9aa1b6487976bd63a6196870':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@ee1b7788cd3f877c9aa1b6487976bd63a6196870}
@@ -1340,8 +1341,8 @@ packages:
'@types/prop-types@15.7.14':
resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==}
- '@types/react@18.3.23':
- resolution: {integrity: sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==}
+ '@types/react@18.3.22':
+ resolution: {integrity: sha512-vUhG0YmQZ7kL/tmKLrD3g5zXbXXreZXB3pmROW8bg3CnLnpjkRVwUlLne7Ufa2r9yJ8+/6B73RzhAek5TBKh2Q==}
'@types/remarkable@2.0.8':
resolution: {integrity: sha512-eKXqPZfpQl1kOADjdKchHrp2gwn9qMnGXhH/AtZe0UrklzhGJkawJo/Y/D0AlWcdWoWamFNIum8+/nkAISQVGg==}
@@ -3635,7 +3636,7 @@ snapshots:
'@analytics/type-utils@0.6.2': {}
- '@appwrite.io/console@1.9.0': {}
+ '@appwrite.io/console@https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@56743f5': {}
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@ee1b7788cd3f877c9aa1b6487976bd63a6196870(svelte@5.25.3)':
dependencies:
@@ -4791,7 +4792,7 @@ snapshots:
'@types/prop-types@15.7.14': {}
- '@types/react@18.3.23':
+ '@types/react@18.3.22':
dependencies:
'@types/prop-types': 15.7.14
csstype: 3.1.3
@@ -6752,7 +6753,7 @@ snapshots:
svelte-motion@0.12.2(svelte@5.25.3):
dependencies:
- '@types/react': 18.3.23
+ '@types/react': 18.3.22
framesync: 6.1.2
popmotion: 11.0.5
style-value-types: 5.1.2
diff --git a/src/lib/components/billing/selectPaymentMethod.svelte b/src/lib/components/billing/selectPaymentMethod.svelte
index 7dfe14a2ed..9a7265c8b7 100644
--- a/src/lib/components/billing/selectPaymentMethod.svelte
+++ b/src/lib/components/billing/selectPaymentMethod.svelte
@@ -11,9 +11,9 @@
import { invalidate } from '$app/navigation';
import { Dependencies } from '$lib/constants';
- export let methods: PaymentList;
export let value: string;
export let taxId = '';
+ export let methods: PaymentList;
let showTaxId = false;
let showPaymentModal = false;
diff --git a/src/lib/components/bottom-sheet/SheetMenuBlock.svelte b/src/lib/components/bottom-sheet/SheetMenuBlock.svelte
index a8d65c4be2..6bc3d2cab9 100644
--- a/src/lib/components/bottom-sheet/SheetMenuBlock.svelte
+++ b/src/lib/components/bottom-sheet/SheetMenuBlock.svelte
@@ -11,7 +11,7 @@
{#if menu?.title}
{/if}
-
+
{#each menu.items as menuItem}
{#if menuItem.href}
import { createMenubar, melt } from '@melt-ui/svelte';
- import { Badge, Icon, type SheetMenu, ActionMenu, Card } from '@appwrite.io/pink-svelte';
+ import {
+ Badge,
+ Icon,
+ type SheetMenu,
+ Layout,
+ ActionMenu,
+ Card,
+ Skeleton
+ } from '@appwrite.io/pink-svelte';
import {
IconChevronDown,
IconChevronRight,
@@ -14,20 +22,13 @@
import { base } from '$app/paths';
import { currentPlan, newOrgModal } from '$lib/stores/organization';
import { Click, trackEvent } from '$lib/actions/analytics';
- import { page } from '$app/stores';
+ import type { Models } from '@appwrite.io/console';
- type Project = {
- name: string;
- $id: string;
- isSelected: boolean;
- region: string;
- };
type Organization = {
name: string;
$id: string;
tierName: string;
isSelected: boolean;
- projects: Array;
};
const {
@@ -62,13 +63,15 @@
}
} = createMenu();
- export let organizations: Organization[] = [];
+ let isLoadingProjects = true;
+ let loadedProjects: Models.ProjectList = { total: 0, projects: [] };
- $: selectedOrg = organizations.find((organization) => organization.isSelected);
- $: selectedProject = $page.data.project;
+ export let organizations: Organization[] = [];
+ export let currentProject: Models.Project | null = null;
+ export let projects: Promise = Promise.resolve(loadedProjects);
- let organisationBottomSheetOpen = false;
let projectsBottomSheetOpen = false;
+ let organisationBottomSheetOpen = false;
function createOrg() {
trackEvent(Click.OrganizationClickCreate, { source: 'breadcrumbs' });
@@ -96,85 +99,76 @@
}
};
- $: organizationsBottomSheet = !selectedOrg
- ? switchOrganization
- : ({
- top: {
- items: [
- {
- name: 'Organization overview',
- href: `${base}/organization-${selectedOrg?.$id}`
- }
- ]
- },
- bottom:
- organizations.length > 1
- ? {
- items: [
- {
- name: 'Switch organization',
- trailingIcon: IconChevronRight,
- subMenu: switchOrganization
- }
- ]
- }
- : {
- items: [
- {
- name: 'Create organization',
- leadingIcon: IconPlus,
- onClick: createOrg
- }
- ]
- }
- } satisfies SheetMenu);
-
- $: projectsBottomSheet = {
- top:
- selectedOrg?.projects.length > 1
- ? {
- title: 'Switch project',
- items: !selectedOrg
- ? []
- : selectedOrg?.projects
- .map((project, index) => {
- if (index < 4) {
- return {
- name: project.name,
- href: `${base}/project-${project.region}-${project.$id}/overview`
- };
- } else if (index === 4) {
- return {
- name: 'All projects',
- href: `${base}/organization-${selectedOrg?.$id}`
- };
- }
- return null;
- })
- .filter((project) => project !== null)
- }
- : {
+ async function createProjectsBottomSheet(organization: Organization): Promise {
+ isLoadingProjects = true;
+ loadedProjects = await projects;
+ isLoadingProjects = false;
+
+ const createProjectItem = {
+ name: 'Create project',
+ trailingIcon: IconPlus,
+ href: `${base}/organization-${organization?.$id}?create-project`
+ };
+
+ if (loadedProjects.total > 1 && selectedOrg) {
+ const projectLinks = loadedProjects.projects.slice(0, 4).map((project) => ({
+ name: project.name,
+ href: `${base}/project-${project.region}-${project.$id}/overview/platforms`
+ }));
+
+ if (loadedProjects.projects.length > 4) {
+ projectLinks.push({
+ name: 'All projects',
+ href: `${base}/organization-${selectedOrg.$id}`
+ });
+ }
+
+ return {
+ top: { title: 'Switch project', items: projectLinks },
+ bottom: { items: [createProjectItem] }
+ };
+ }
+
+ return {
+ top: { items: [createProjectItem] },
+ bottom: { items: [createProjectItem] }
+ };
+ }
+
+ function createOrganizationBottomSheet(organization: Organization) {
+ return !organization
+ ? switchOrganization
+ : ({
+ top: {
items: [
{
- name: 'Create project',
- trailingIcon: IconPlus,
- href: `${base}/organization-${selectedOrg?.$id}?create-project`
+ name: 'Organization overview',
+ href: `${base}/organization-${organization?.$id}`
}
]
},
- bottom:
- selectedOrg?.projects.length > 1
- ? {
- items: [
- {
- name: 'Create project',
- trailingIcon: IconPlus,
- href: `${base}/organization-${selectedOrg?.$id}?create-project`
- }
- ]
- }
- : undefined
- } satisfies SheetMenu;
+ bottom:
+ organizations.length > 1
+ ? {
+ items: [
+ {
+ name: 'Switch organization',
+ trailingIcon: IconChevronRight,
+ subMenu: switchOrganization
+ }
+ ]
+ }
+ : {
+ items: [
+ {
+ name: 'Create organization',
+ leadingIcon: IconPlus,
+ onClick: createOrg
+ }
+ ]
+ }
+ } satisfies SheetMenu);
+ }
function onResize() {
if ((organisationBottomSheetOpen || projectsBottomSheetOpen) && !$isSmallViewport) {
@@ -183,6 +177,12 @@
}
}
+ $: selectedOrg = organizations.find((org) => org.isSelected);
+
+ $: projectsBottomSheet = createProjectsBottomSheet(selectedOrg);
+
+ $: organizationsBottomSheet = createOrganizationBottomSheet(selectedOrg);
+
$: correctPlanName =
// the plan names are hardcoded in some cases and are not available locally,
// so we rely on the plan's source of truth - `$currentPlan`
@@ -191,7 +191,7 @@
? $currentPlan.name
: selectedOrg?.tierName; // fallback
- $: derivedKey = `${selectedOrg?.$id}-${selectedProject?.$id}`;
+ $: derivedKey = `${selectedOrg?.$id}-${currentProject?.$id}`;
@@ -220,7 +220,7 @@
organisationBottomSheetOpen = true;
}}
aria-label="Open organizations tab">
- {selectedOrg?.name ?? 'Organization'}
@@ -302,7 +302,7 @@
- {#if selectedOrg && selectedProject}
+ {#if selectedOrg && currentProject}
/
{#if !$isSmallViewport}
{:else}
@@ -319,20 +319,28 @@
class="trigger"
on:click={() => (projectsBottomSheetOpen = true)}
aria-label="Open projects tab">
- {selectedProject.name}
+ {currentProject.name}
{/if}