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} {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}